From 1c5a22a071c08245700d2287aab3aa48478805bd Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Fri, 28 Jan 2022 18:24:03 +0100 Subject: [PATCH] virtual references working --- packages/api/src/controllers/apps.js | 8 +++++ packages/datalib/src/GridDisplay.ts | 1 + packages/datalib/src/TableGridDisplay.ts | 24 +++++++++++---- packages/tools/src/structureTools.ts | 30 ++++++++++++++++++- packages/types/appdefs.d.ts | 12 ++++++++ packages/types/index.d.ts | 1 + .../web/src/datagrid/TableDataGrid.svelte | 9 ++++-- 7 files changed, 76 insertions(+), 9 deletions(-) diff --git a/packages/api/src/controllers/apps.js b/packages/api/src/controllers/apps.js index 80ee2e65..e07be5c5 100644 --- a/packages/api/src/controllers/apps.js +++ b/packages/api/src/controllers/apps.js @@ -185,6 +185,14 @@ module.exports = { await processType('.query.sql', 'queries'); } + try { + res.virtualReferences = JSON.parse( + await fs.readFile(path.join(dir, 'virtual-references.json'), { encoding: 'utf-8' }) + ); + } catch (err) { + res.virtualReferences = []; + } + return res; }, diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts index e347af3e..29604143 100644 --- a/packages/datalib/src/GridDisplay.ts +++ b/packages/datalib/src/GridDisplay.ts @@ -28,6 +28,7 @@ export interface DisplayColumn { autoIncrement?: boolean; isPrimaryKey?: boolean; foreignKey?: ForeignKeyInfo; + isForeignKeyUnique?: boolean; isExpandable?: boolean; isChecked?: boolean; hintColumnNames?: string[]; diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index cd8227a2..e9480835 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { filterName } from 'dbgate-tools'; +import { filterName, isTableColumnUnique } from 'dbgate-tools'; import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay'; import { TableInfo, @@ -79,10 +79,11 @@ export class TableGridDisplay extends GridDisplay { ...col, isChecked: this.isColumnChecked(col), hintColumnNames: - this.getFkDictionaryDescription(col.foreignKey)?.columns?.map( + this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map( columnName => `hint_${col.uniqueName}_${columnName}` ) || null, - hintColumnDelimiter: this.getFkDictionaryDescription(col.foreignKey)?.delimiter, + hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null) + ?.delimiter, isExpandable: !!col.foreignKey, })) || [] ); @@ -203,7 +204,8 @@ export class TableGridDisplay extends GridDisplay { } getFkTarget(column: DisplayColumn) { - const { uniqueName, foreignKey } = column; + const { uniqueName, foreignKey, isForeignKeyUnique } = column; + if (!isForeignKeyUnique) return null; const pureName = foreignKey.refTableName; const schemaName = foreignKey.refSchemaName; return this.findTable({ schemaName, pureName }); @@ -230,7 +232,7 @@ export class TableGridDisplay extends GridDisplay { const uniquePath = [...parentPath, col.columnName]; const uniqueName = uniquePath.join('.'); // console.log('this.config.addedColumns', this.config.addedColumns, uniquePath); - return { + const res = { ...col, pureName: table.pureName, schemaName: table.schemaName, @@ -241,7 +243,19 @@ export class TableGridDisplay extends GridDisplay { foreignKey: table.foreignKeys && table.foreignKeys.find(fk => fk.columns.length == 1 && fk.columns[0].columnName == col.columnName), + isForeignKeyUnique: false, }; + + if (res.foreignKey) { + const refTableInfo = this.dbinfo.tables.find( + x => x.schemaName == res.foreignKey.refSchemaName && x.pureName == res.foreignKey.refTableName + ); + if (refTableInfo && isTableColumnUnique(refTableInfo, res.foreignKey.columns[0].refColumnName)) { + res.isForeignKeyUnique = true; + } + } + + return res; } addAddedColumnsToSelect( diff --git a/packages/tools/src/structureTools.ts b/packages/tools/src/structureTools.ts index 8c6d9248..a49f3a76 100644 --- a/packages/tools/src/structureTools.ts +++ b/packages/tools/src/structureTools.ts @@ -1,4 +1,4 @@ -import { DatabaseInfo, TableInfo } from 'dbgate-types'; +import { DatabaseInfo, TableInfo, ApplicationDefinition } from 'dbgate-types'; import _flatten from 'lodash/flatten'; export function addTableDependencies(db: DatabaseInfo): DatabaseInfo { @@ -90,3 +90,31 @@ function fillDatabaseExtendedInfo(db: DatabaseInfo): DatabaseInfo { 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, isVirtual: true })), + ], + })), + }; + 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; +} diff --git a/packages/types/appdefs.d.ts b/packages/types/appdefs.d.ts index ff63dda4..4d45f5a5 100644 --- a/packages/types/appdefs.d.ts +++ b/packages/types/appdefs.d.ts @@ -8,9 +8,21 @@ interface ApplicationQuery { sql: string; } +interface VirtualReferenceDefinition { + pureName: string; + schemaName?: string; + refSchemaName?: string; + refTableName: string; + columns: { + columnName: string; + refColumnName: string; + }[]; +} + interface ApplicationDefinition { name: string; queries: ApplicationQuery[]; commands: ApplicationCommand[]; + virtualReferences: VirtualReferenceDefinition[]; } diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index aed04c88..e7f8ad0a 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -43,3 +43,4 @@ export * from './dumper'; export * from './dbtypes'; export * from './extensions'; export * from './alter-processor'; +export * from './appdefs'; diff --git a/packages/web/src/datagrid/TableDataGrid.svelte b/packages/web/src/datagrid/TableDataGrid.svelte index 2dc81a4f..2e1824d9 100644 --- a/packages/web/src/datagrid/TableDataGrid.svelte +++ b/packages/web/src/datagrid/TableDataGrid.svelte @@ -7,7 +7,7 @@ TableGridDisplay, } from 'dbgate-datalib'; import { getFilterValueExpression } from 'dbgate-filterparser'; - import { findEngineDriver } from 'dbgate-tools'; + import { extendDatabaseInfoFromApps, findEngineDriver } from 'dbgate-tools'; import _ from 'lodash'; import { writable } from 'svelte/store'; import VerticalSplitter from '../elements/VerticalSplitter.svelte'; @@ -19,6 +19,7 @@ useDatabaseInfo, useDatabaseServerVersion, useServerVersion, + useUsedApps, } from '../utility/metadataLoaders'; import DataGrid from './DataGrid.svelte'; @@ -46,6 +47,8 @@ $: connection = useConnectionInfo({ conid }); $: dbinfo = useDatabaseInfo({ conid, database }); $: serverVersion = useDatabaseServerVersion({ conid, database }); + $: apps = useUsedApps(); + $: extendedDbInfo = extendDatabaseInfoFromApps($dbinfo, $apps); // $: console.log('serverVersion', $serverVersion); @@ -64,7 +67,7 @@ setConfig, cache, setCache, - $dbinfo, + extendedDbInfo, { showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) }, $serverVersion, table => getDictionaryDescription(table, conid, database) @@ -80,7 +83,7 @@ setConfig, cache, setCache, - $dbinfo, + extendedDbInfo, { showHintColumns: getBoolSettingsValue('dataGrid.showHintColumns', true) }, $serverVersion, table => getDictionaryDescription(table, conid, database)