diff --git a/packages/datalib/src/PerspectiveTreeNode.ts b/packages/datalib/src/PerspectiveTreeNode.ts index 0ecb37d9c..5b0a6096d 100644 --- a/packages/datalib/src/PerspectiveTreeNode.ts +++ b/packages/datalib/src/PerspectiveTreeNode.ts @@ -75,6 +75,9 @@ export abstract class PerspectiveTreeNode { get dataField() { return this.codeName; } + get tableCode() { + return null; + } abstract getNodeLoadProps(parentRows: any[]): PerspectiveDataLoadProps; get isRoot() { return this.parentNode == null; @@ -83,6 +86,10 @@ export abstract class PerspectiveTreeNode { return true; } + hasTableCode(code: string) { + return code == this.tableCode || this.parentNode?.hasTableCode(code); + } + get uniqueName() { if (this.parentNode) return `${this.parentNode.uniqueName}.${this.codeName}`; return this.codeName; @@ -254,13 +261,10 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { setConfig: ChangePerspectiveConfigFunc, dataProvider: PerspectiveDataProvider, databaseConfig: PerspectiveDatabaseConfig, - parentNode: PerspectiveTreeNode, - defaultChecked: boolean + parentNode: PerspectiveTreeNode ) { super(config, setConfig, parentNode, dataProvider, databaseConfig); - this.defaultChecked = defaultChecked; - this.foreignKey = (table as TableInfo)?.foreignKeys?.find( fk => fk.columns.length == 1 && fk.columns[0].columnName == column.columnName ); @@ -303,6 +307,7 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { } get icon() { + if (this.isCircular) return 'img circular'; if (this.column.autoIncrement) return 'img autoincrement'; if (this.foreignKey) return 'img foreign-key'; return 'img column'; @@ -332,6 +337,10 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { return getFilterType(this.column.dataType); } + get isCircular() { + return !!this.parentNode?.parentNode?.hasTableCode(this.tableCode); + } + get childNodes(): PerspectiveTreeNode[] { if (!this.foreignKey) return []; const tbl = this?.db?.tables?.find( @@ -391,6 +400,13 @@ export class PerspectiveTableColumnNode extends PerspectiveTreeNode { } return null; } + + get tableCode() { + if (this.foreignKey) { + return `${this.foreignKey.refSchemaName}|${this.foreignKey.refTableName}`; + } + return `${this.table.schemaName}|${this.table.pureName}`; + } } export class PerspectiveTableNode extends PerspectiveTreeNode { @@ -457,6 +473,10 @@ export class PerspectiveTableNode extends PerspectiveTreeNode { database: this.databaseConfig.database, }; } + + get tableCode() { + return `${this.table.schemaName}|${this.table.pureName}`; + } } export class PerspectiveViewNode extends PerspectiveTreeNode { @@ -580,7 +600,6 @@ export class PerspectiveTableReferenceNode extends PerspectiveTableNode { } return super.codeName; } - } export class PerspectiveCustomJoinTreeNode extends PerspectiveTableNode { @@ -667,25 +686,17 @@ export function getTableChildPerspectiveNodes( ) { if (!table) return []; - const defaultColumns = getPerspectiveDefaultColumns(table, db); + const columnNodes = table.columns.map( + col => new PerspectiveTableColumnNode(col, table, db, config, setConfig, dataProvider, databaseConfig, parentColumn) + ); + const circularColumns = columnNodes.filter(x => x.isCircular).map(x => x.columnName); + const defaultColumns = getPerspectiveDefaultColumns(table, db, circularColumns); + for (const node of columnNodes) { + node.defaultChecked = defaultColumns.includes(node.columnName); + } const res = []; - res.push( - ...table.columns.map( - col => - new PerspectiveTableColumnNode( - col, - table, - db, - config, - setConfig, - dataProvider, - databaseConfig, - parentColumn, - defaultColumns.includes(col.columnName) - ) - ) - ); + res.push(...columnNodes); const dependencies = []; if (db && (table as TableInfo)?.dependencies) { for (const fk of (table as TableInfo)?.dependencies) { diff --git a/packages/datalib/src/getPerspectiveDefaultColumns.ts b/packages/datalib/src/getPerspectiveDefaultColumns.ts index 1eabe08ee..e097f546c 100644 --- a/packages/datalib/src/getPerspectiveDefaultColumns.ts +++ b/packages/datalib/src/getPerspectiveDefaultColumns.ts @@ -1,7 +1,11 @@ import { findForeignKeyForColumn } from 'dbgate-tools'; import { DatabaseInfo, TableInfo, ViewInfo } from 'dbgate-types'; -export function getPerspectiveDefaultColumns(table: TableInfo | ViewInfo, db: DatabaseInfo): string[] { +export function getPerspectiveDefaultColumns( + table: TableInfo | ViewInfo, + db: DatabaseInfo, + circularColumns: string[] +): string[] { const columns = table.columns.map(x => x.columnName); const predicates = [ x => x.toLowerCase() == 'name', @@ -9,6 +13,7 @@ export function getPerspectiveDefaultColumns(table: TableInfo | ViewInfo, db: Da x => x.toLowerCase().includes('name'), x => x.toLowerCase().includes('title'), x => x.dataType?.toLowerCase()?.includes('char'), + x => findForeignKeyForColumn(table as TableInfo, x)?.columns?.length == 1 && !circularColumns.includes(x), x => findForeignKeyForColumn(table as TableInfo, x)?.columns?.length == 1, ]; diff --git a/packages/web/src/icons/FontIcon.svelte b/packages/web/src/icons/FontIcon.svelte index 96ddeaf07..3299132f7 100644 --- a/packages/web/src/icons/FontIcon.svelte +++ b/packages/web/src/icons/FontIcon.svelte @@ -121,6 +121,7 @@ 'img warn': 'mdi mdi-alert color-icon-gold', 'img info': 'mdi mdi-information color-icon-blue', // 'img statusbar-ok': 'mdi mdi-check-circle color-on-statusbar-green', + 'img circular': 'mdi mdi-circular-saw color-icon-red', 'img archive': 'mdi mdi-table color-icon-gold', 'img archive-folder': 'mdi mdi-database-outline color-icon-green',