Files
dbgate/packages/tools/src/structureTools.ts
2024-11-08 09:12:28 +01:00

171 lines
5.3 KiB
TypeScript

import type { DatabaseInfo, TableInfo, ApplicationDefinition, ViewInfo, CollectionInfo } from 'dbgate-types';
import _flatten from 'lodash/flatten';
import _uniq from 'lodash/uniq';
export function addTableDependencies(db: DatabaseInfo): DatabaseInfo {
if (!db.tables) {
return db;
}
const allForeignKeys = _flatten(db.tables.map(x => x.foreignKeys || []));
return {
...db,
tables: db.tables.map(table => ({
...table,
dependencies: allForeignKeys.filter(x => x.refSchemaName == table.schemaName && x.refTableName == table.pureName),
})),
};
}
export function extendTableInfo(table: TableInfo): TableInfo {
return {
...table,
objectTypeField: 'tables',
columns: (table.columns || []).map(column => ({
pureName: table.pureName,
schemaName: table.schemaName,
...column,
})),
primaryKey: table.primaryKey
? {
...table.primaryKey,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'primaryKey',
}
: undefined,
sortingKey: table.sortingKey
? {
...table.sortingKey,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'sortingKey',
}
: undefined,
foreignKeys: (table.foreignKeys || []).map(cnt => ({
...cnt,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'foreignKey',
})),
indexes: (table.indexes || []).map(cnt => ({
...cnt,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'index',
})),
checks: (table.checks || []).map(cnt => ({
...cnt,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'check',
})),
uniques: (table.uniques || []).map(cnt => ({
...cnt,
pureName: table.pureName,
schemaName: table.schemaName,
constraintType: 'unique',
})),
};
}
function fillDatabaseExtendedInfo(db: DatabaseInfo): DatabaseInfo {
return {
...db,
tables: (db.tables || []).map(extendTableInfo),
collections: (db.collections || []).map(obj => ({
...obj,
objectTypeField: 'collections',
})),
views: (db.views || []).map(obj => ({
...obj,
objectTypeField: 'views',
})),
matviews: (db.matviews || []).map(obj => ({
...obj,
objectTypeField: 'matviews',
})),
procedures: (db.procedures || []).map(obj => ({
...obj,
objectTypeField: 'procedures',
})),
functions: (db.functions || []).map(obj => ({
...obj,
objectTypeField: 'functions',
})),
triggers: (db.triggers || []).map(obj => ({
...obj,
objectTypeField: 'triggers',
})),
};
}
export function extendDatabaseInfo(db: DatabaseInfo): DatabaseInfo {
return fillDatabaseExtendedInfo(addTableDependencies(db));
}
export function extendDatabaseInfoFromApps(db: DatabaseInfo, apps: ApplicationDefinition[]): DatabaseInfo {
if (!db || !apps) return db;
const dbExt = {
...db,
tables: db.tables.map(table => ({
...table,
foreignKeys: [
...(table.foreignKeys || []),
..._flatten(apps.map(app => app.virtualReferences || []))
.filter(fk => fk.pureName == table.pureName && fk.schemaName == table.schemaName)
.map(fk => ({ ...fk, constraintType: 'foreignKey', isVirtual: true })),
],
})),
} as DatabaseInfo;
return addTableDependencies(dbExt);
}
export function isTableColumnUnique(table: TableInfo, column: string) {
if (table.primaryKey && table.primaryKey.columns.length == 1 && table.primaryKey.columns[0].columnName == column) {
return true;
}
const uqs = [...(table.uniques || []), ...(table.indexes || []).filter(x => x.isUnique)];
if (uqs.find(uq => uq.columns.length == 1 && uq.columns[0].columnName == column)) {
return true;
}
return false;
}
export function isTableInfo(obj: { objectTypeField?: string }): obj is TableInfo {
return obj.objectTypeField == 'tables';
}
export function isViewInfo(obj: { objectTypeField?: string }): obj is ViewInfo {
return obj.objectTypeField == 'views';
}
export function isCollectionInfo(obj: { objectTypeField?: string }): obj is CollectionInfo {
return obj.objectTypeField == 'collections';
}
export function filterStructureBySchema(db: DatabaseInfo, schema: string) {
return {
...db,
tables: (db.tables || []).filter(x => x.schemaName == schema),
views: (db.views || []).filter(x => x.schemaName == schema),
collections: (db.collections || []).filter(x => x.schemaName == schema),
matviews: (db.matviews || []).filter(x => x.schemaName == schema),
procedures: (db.procedures || []).filter(x => x.schemaName == schema),
functions: (db.functions || []).filter(x => x.schemaName == schema),
triggers: (db.triggers || []).filter(x => x.schemaName == schema),
};
}
export function getSchemasUsedByStructure(db: DatabaseInfo) {
return _uniq([
...(db.tables || []).map(x => x.schemaName),
...(db.views || []).map(x => x.schemaName),
...(db.collections || []).map(x => x.schemaName),
...(db.matviews || []).map(x => x.schemaName),
...(db.procedures || []).map(x => x.schemaName),
...(db.functions || []).map(x => x.schemaName),
...(db.triggers || []).map(x => x.schemaName),
]);
}