foreign evolution
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
jusax23 2023-02-14 17:37:01 +01:00
parent ea3100c4ae
commit d763d2a35e
4 changed files with 101 additions and 27 deletions

View file

@ -1,5 +1,5 @@
import mariadb from 'mariadb'; import mariadb from 'mariadb';
import { checkConstraint, Constraint, Datatype, uniqueConstraint } from './dbStructure'; import { checkConstraint, Constraint, Datatype, foreignConstraint, uniqueConstraint } from './dbStructure';
import { Handler } from './defaultHandler'; import { Handler } from './defaultHandler';
import { Query } from './query'; import { Query } from './query';
import { attributeSettings, extendedAttributeSettings, onAction } from './types'; import { attributeSettings, extendedAttributeSettings, onAction } from './types';
@ -67,6 +67,15 @@ export class Attribute {
[this] [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) { serializeDatatype(handler: Handler) {
return this.type.serialize(handler); return this.type.serialize(handler);

View file

@ -1,7 +1,7 @@
import { Attribute, Table } from "./db"; import { Attribute, Table } from "./db";
import { Handler } from "./defaultHandler"; import { Handler } from "./defaultHandler";
import { QueryBuilder } from "./query"; import { QueryBuilder } from "./query";
import { allModifierInput, primaryData, serializeReturn } from "./types"; import { allModifierInput, onAction, primaryData, serializeReturn } from "./types";
export class Datatype { export class Datatype {
type: string; type: string;
@ -101,10 +101,14 @@ export class foreignConstraint implements Constraint {
name: string; name: string;
fromAttrs: Attribute[]; fromAttrs: Attribute[];
toAttrs: Attribute[]; toAttrs: Attribute[];
constructor(name: string, from: Attribute[], to: Attribute[]) { onUpdate: onAction;
onDelete: onAction;
constructor(name: string, from: Attribute[], to: Attribute[], onDelete: onAction = onAction.nothing, onUpdate: onAction = onAction.nothing) {
this.name = name.toLowerCase(); this.name = name.toLowerCase();
this.fromAttrs = from; this.fromAttrs = from;
this.toAttrs = to; this.toAttrs = to;
this.onUpdate = onUpdate;
this.onDelete = onDelete;
} }
serialize(handler: Handler): QueryBuilder { serialize(handler: Handler): QueryBuilder {
throw new Error("Method not implemented."); throw new Error("Method not implemented.");

View file

@ -1,7 +1,7 @@
import { Attribute, DB, Table } from "./db" import { Attribute, DB, Table } from "./db"
import { Aggregation, checkConstraint, Constraint, Datatype, Modifier, uniqueConstraint } from "./dbStructure" import { Aggregation, checkConstraint, Constraint, Datatype, foreignConstraint, Modifier, uniqueConstraint } from "./dbStructure"
import { Query, QueryBuilder, selectQuery } from "./query" import { Query, QueryBuilder, selectQuery } from "./query"
import { allModifierInput, primaryData, serializeReturn } from "./types" import { allModifierInput, onAction, primaryData, serializeReturn } from "./types"
export class Handler { export class Handler {
async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) { async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) {
@ -19,8 +19,10 @@ export class Handler {
let [key, constraints] = await db.query(handler.builders.query(gd)); let [key, constraints] = await db.query(handler.builders.query(gd));
//Table List
let allTables = (await db.query(handler.builders.query(handler.querys.listTables(handler, db)))).map((d: any) => d.TABLE_NAME); let allTables = (await db.query(handler.builders.query(handler.querys.listTables(handler, db)))).map((d: any) => d.TABLE_NAME);
// gether Table Schematics
let tableData: { [key: string]: any; } = {}; let tableData: { [key: string]: any; } = {};
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];
@ -45,7 +47,6 @@ export class Handler {
const c = t.dbLangConstrains[i]; const c = t.dbLangConstrains[i];
if (c.name == n.toLowerCase() && c instanceof uniqueConstraint) { if (c.name == n.toLowerCase() && c instanceof uniqueConstraint) {
let attrs = c.attrs.map(a => a.name); let attrs = c.attrs.map(a => a.name);
console.log(attrs);
let found = 0; let found = 0;
for (let j = 0; j < key.length; j++) { for (let j = 0; j < key.length; j++) {
if ( if (
@ -61,6 +62,35 @@ export class Handler {
} }
return false; return false;
} }
function checkForeignIsVaild(n: string, table: string) {
let t = db.getTable(table);
if (t == null) return false;
for (let i = 0; i < t.dbLangConstrains.length; i++) {
const c = t.dbLangConstrains[i];
if (c.name == n.toLowerCase() && c instanceof foreignConstraint) {
let fromAttrs = c.fromAttrs.map(a => a.name);
let toAttrs = c.toAttrs.map(a => a.name);
let refTable = c.toAttrs[0].table.dbLangTableName;
let found = 0;
for (let j = 0; j < key.length; j++) {
if (
key[j].CONSTRAINT_NAME == n
&& key[j].TABLE_NAME == table
&& key[j].REFERENCED_TABLE_NAME == refTable
) {
let inF = fromAttrs.indexOf(key[j].COLUMN_NAME.toLowerCase());
let inT = toAttrs.indexOf(key[j].REFERENCED_COLUMN_NAME.toLowerCase());
if (inF != -1 && inT == inF) found++;
else return false;
}
}
return found == fromAttrs.length && found == toAttrs.length;
}
}
return false;
}
function checkUniqueExists(tabel: Table, c: uniqueConstraint) { function checkUniqueExists(tabel: Table, c: uniqueConstraint) {
let attrs = c.attrs.map(a => a.name); let attrs = c.attrs.map(a => a.name);
let found = 0; let found = 0;
@ -75,6 +105,25 @@ export class Handler {
} }
return found == attrs.length; return found == attrs.length;
} }
function checkForeignExists(tabel: Table, c: foreignConstraint) {
let fromAttrs = c.fromAttrs.map(a => a.name);
let toAttrs = c.toAttrs.map(a => a.name);
let refTable = c.toAttrs[0].table.dbLangTableName;
let found = 0;
for (let j = 0; j < key.length; j++) {
if (
key[j].CONSTRAINT_NAME == c.name
&& key[j].TABLE_NAME == tabel.dbLangTableName
&& key[j].REFERENCED_TABLE_NAME == refTable
) {
let inF = fromAttrs.indexOf(key[j].COLUMN_NAME.toLowerCase());
let inT = toAttrs.indexOf(key[j].REFERENCED_COLUMN_NAME.toLowerCase());
if (inF != -1 && inT == inF) found++;
else return false;
}
}
return found == fromAttrs.length && found == toAttrs.length;
}
//delete check and unused/false(unique, foreign) constraints //delete check and unused/false(unique, foreign) constraints
for (let i = 0; i < constraints.length; i++) { for (let i = 0; i < constraints.length; i++) {
@ -86,15 +135,17 @@ export class Handler {
(typeof tableData[c.TABLE_NAME.toLowerCase()] == "undefined" && deleteInDB) (typeof tableData[c.TABLE_NAME.toLowerCase()] == "undefined" && deleteInDB)
|| !checkUniqueIsVaild(c.CONSTRAINT_NAME, c.TABLE_NAME) || !checkUniqueIsVaild(c.CONSTRAINT_NAME, c.TABLE_NAME)
) del.appendEnding(handler.querys.removeUnique(handler, c.TABLE_NAME, c.CONSTRAINT_NAME)); ) del.appendEnding(handler.querys.removeUnique(handler, c.TABLE_NAME, c.CONSTRAINT_NAME));
} else if (c.CONSTRAINT_TYPE == "FOREIGN KEY" && deleteInDB) { } else if (c.CONSTRAINT_TYPE == "FOREIGN KEY") {
if (typeof tableData[c.TABLE_NAME.toLowerCase()] == "undefined") del.appendEnding(handler.querys.removeForeignKey(handler, c.TABLE_NAME, c.CONSTRAINT_NAME)); if (
(typeof tableData[c.TABLE_NAME.toLowerCase()] == "undefined" && deleteInDB)
|| !checkForeignIsVaild(c.CONSTRAINT_NAME, c.TABLE_NAME)
) del.appendEnding(handler.querys.removeForeignKey(handler, c.TABLE_NAME, c.CONSTRAINT_NAME));
} }
} }
//delete unused Tables //delete unused Tables
if (deleteInDB) for (let i = 0; i < allTables.length; i++) { if (deleteInDB) for (let i = 0; i < allTables.length; i++) {
if (typeof tableData[allTables[i].toLowerCase()] == "undefined") del.appendEnding(handler.querys.deleteTable(handler, allTables[i])); if (typeof tableData[allTables[i].toLowerCase()] == "undefined") del.appendEnding(handler.querys.deleteTable(handler, allTables[i]));
} }
// TODO: delete old constraints/tables
function freeForUpdate(attr: string, table: string) { function freeForUpdate(attr: string, table: string) {
for (let i = 0; i < key.length; i++) { for (let i = 0; i < key.length; i++) {
@ -113,7 +164,7 @@ export class Handler {
const table = db.tables[i]; const table = db.tables[i];
const tableD = tableData[table.dbLangTableName.toLowerCase()]; const tableD = tableData[table.dbLangTableName.toLowerCase()];
//delete unused Columns //delete unused Columns
if (deleteInDB) { if (deleteInDB && tableD != null) {
let keys = Object.keys(tableD); let keys = Object.keys(tableD);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
if (table.dbLangTableAttributes[keys[i]] == null) { if (table.dbLangTableAttributes[keys[i]] == null) {
@ -141,10 +192,10 @@ 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")
) { ) {
console.log(!handler.builders.compareDatatypes(handler, a.type, attrData.Type), "|", /*console.log(!handler.builders.compareDatatypes(handler, a.type, attrData.Type), "|",
a.ops.default, attrData.Default, "|", a.ops.default, attrData.Default, "|",
(!!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)); create.appendEnding(handler.querys.changeColumn(handler, a));
} }
@ -170,10 +221,12 @@ export class Handler {
if (!checkUniqueExists(table, c)) { if (!checkUniqueExists(table, c)) {
create.appendEnding(handler.querys.addUnique(handler, table, c)); create.appendEnding(handler.querys.addUnique(handler, table, c));
} }
} else if (c instanceof foreignConstraint) {
if (!checkForeignExists(table, c)) {
create.appendEnding(handler.querys.addForeignKey(handler, table, c));
}
} }
} }
// TODO: unique, foreignkey
} }
if (!create.isEmpty()) del.append(create); if (!create.isEmpty()) del.append(create);
if (!del.isEmpty()) await db.query(handler.builders.query(del)); if (!del.isEmpty()) await db.query(handler.builders.query(del));
@ -262,22 +315,29 @@ export class Handler {
builder.addCode(handler.builders.escapeID(attr)); builder.addCode(handler.builders.escapeID(attr));
return builder; return builder;
}, },
addForeignKey: (handler: Handler, attr: Attribute, target: Attribute) => { addForeignKey: (handler: Handler, table: Table, c: foreignConstraint) => {
const builder = new QueryBuilder(); const builder = new QueryBuilder();
builder.addCode("ALTER TABLE "); builder.addCode("ALTER TABLE ");
builder.addCode(attr.table.serialize(handler)); builder.addCode(table.serialize(handler));
builder.addCode(" ADD CONSTRAINT "); builder.addCode(" ADD CONSTRAINT ");
builder.addCode(handler.builders.escapeID(attr.table.dbLangDatabaseInstance.name builder.addCode(handler.builders.escapeID(c.name));
+ "_" + attr.table.dbLangTableName
+ "_" + attr.name + "_foreign_key_constraint_to_"
+ target.table.dbLangTableName + "_" + target.name));
builder.addCode(" FOREIGN KEY ("); builder.addCode(" FOREIGN KEY (");
builder.addCode(attr.serialize(handler)); builder.addCodeCommaSeperated(c.fromAttrs.map(a => a.serialize(handler)));
builder.addCode(") REFERENCES "); builder.addCode(") REFERENCES ");
builder.addCode(target.table.serialize(handler)); builder.addCode(c.toAttrs[0].table.serialize(handler));
builder.addCode("("); builder.addCode("(");
builder.addCode(target.serialize(handler)); builder.addCodeCommaSeperated(c.toAttrs.map(a => a.serialize(handler)));
builder.addCode(")"); builder.addCode(")");
if (c.onUpdate == onAction.cascade) builder.addCode(" ON UPDATE CASCADE");
if (c.onUpdate == onAction.noAction) builder.addCode(" ON UPDATE NO ACTION");
if (c.onUpdate == onAction.setDefault) builder.addCode(" ON UPDATE SET DEFUALT");
if (c.onUpdate == onAction.setNull) builder.addCode(" ON UPDATE SET NULL");
if (c.onDelete == onAction.cascade) builder.addCode(" ON DELETE CASCADE");
if (c.onDelete == onAction.noAction) builder.addCode(" ON DELETE NO ACTION");
if (c.onDelete == onAction.setDefault) builder.addCode(" ON DELETE SET DEFUALT");
if (c.onDelete == onAction.setNull) builder.addCode(" ON DELETE SET NULL");
return builder; return builder;
}, },
removeForeignKey: (handler: Handler, tablenName: string, name: string) => { removeForeignKey: (handler: Handler, tablenName: string, name: string) => {

View file

@ -42,6 +42,7 @@ export type extendedAttributeSettings = {
} }
export enum onAction { export enum onAction {
nothing,
cascade, cascade,
noAction, noAction,
setNull, setNull,