diff --git a/packages/nc-gui/components/smartsheet/column/LookupOptions.vue b/packages/nc-gui/components/smartsheet/column/LookupOptions.vue index b205d4f06c..582108fb37 100644 --- a/packages/nc-gui/components/smartsheet/column/LookupOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/LookupOptions.vue @@ -50,7 +50,7 @@ const columns = $computed(() => { if (!selectedTable?.id) { return [] } - return metas[selectedTable.id].columns.filter((c: ColumnType) => !isSystemColumn(c)) + return metas[selectedTable.id].columns.filter((c: ColumnType) => !isSystemColumn(c) && c.id !== vModel.value.id) }) onMounted(() => { diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index dcc04d7bf5..f039144f72 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -40,8 +40,8 @@ import { MetaTable } from '../../utils/globals'; import formulaQueryBuilderv2 from '../../db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2'; import { createHmAndBtColumn, - validateRequiredField, validateLookupPayload, + validateRequiredField, validateRollupPayload, } from './helpers'; @@ -626,9 +626,12 @@ export async function columnSetAsPrimary(req: Request, res: Response) { async function updateRollupOrLookup(colBody: any, column: Column) { if ( UITypes.Lookup === column.uidt && - validateRequiredField(colBody, ['fk_lookup_column_id', 'fk_relation_column_id']) + validateRequiredField(colBody, [ + 'fk_lookup_column_id', + 'fk_relation_column_id', + ]) ) { - await validateLookupPayload(colBody); + await validateLookupPayload(colBody, column.id); await Column.update(column.id, colBody); } else if ( UITypes.Rollup === column.uidt && diff --git a/packages/nocodb/src/lib/meta/api/helpers/columnHelpers.ts b/packages/nocodb/src/lib/meta/api/helpers/columnHelpers.ts index ae9e6b00dd..b9847b0627 100644 --- a/packages/nocodb/src/lib/meta/api/helpers/columnHelpers.ts +++ b/packages/nocodb/src/lib/meta/api/helpers/columnHelpers.ts @@ -8,6 +8,7 @@ import { } from 'nocodb-sdk'; import Column from '../../../models/Column'; import LinkToAnotherRecordColumn from '../../../models/LinkToAnotherRecordColumn'; +import LookupColumn from '../../../models/LookupColumn'; import Model from '../../../models/Model'; import { getUniqueColumnAliasName } from '../../helpers/getUniqueName'; import validateParams from '../../helpers/validateParams'; @@ -111,13 +112,33 @@ export async function validateRollupPayload( } export async function validateLookupPayload( - payload: ColumnReqType & { uidt: UITypes } + payload: ColumnReqType & { uidt: UITypes }, + columnId?: string ) { validateParams( ['title', 'fk_relation_column_id', 'fk_lookup_column_id'], payload ); + // check for circular reference + if (columnId) { + let lkCol: LookupColumn | LookupColumnReqType = + payload as LookupColumnReqType; + while (lkCol) { + // check if lookup column is same as column itself + if (columnId === lkCol.fk_lookup_column_id) + throw new Error('Circular lookup reference not allowed'); + lkCol = await Column.get({ colId: lkCol.fk_lookup_column_id }).then( + (c: Column) => { + if (c.uidt === 'Lookup') { + return c.getColOptions(); + } + return null; + } + ); + } + } + const relation = await ( await Column.get({ colId: (payload as LookupColumnReqType).fk_relation_column_id,