From e94d90894bcf17b40d4cfbe99570dcf91a22ac00 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 13 May 2025 16:22:59 +0200 Subject: [PATCH] Fix relation deletion (#12008) ## What This PR fixes a regression tied to the new relation format refactoring. I'm also slightly improving the performance by decreasing the number of queries. ## Considerations 1. I've started adding an integration test to cover relation creation and deletion but we are still using the r`elation-metadata.service` to create a relation and the `field-metadata.service` to delete it. As we plan to fully deprecate the `relation-metadata.service`, I did not want to invest into writing test tooling to change it in a few weeks so I've reverted the test 2. We are still maintaining relationMetadata table up-to-date (so deleting them when we delete the field). relationMetadata full deprecation is up coming but I'm waiting a bit so we don't have breaking changes in 0.53 --- .../field-metadata/field-metadata.service.ts | 106 ++++++++++-------- 1 file changed, 60 insertions(+), 46 deletions(-) diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts index c3967a10b..5f34cc407 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts @@ -318,31 +318,30 @@ export class FieldMetadataService extends TypeOrmQueryService) .settings?.relationType === RelationType.MANY_TO_ONE; - const targetFieldMetadata = - await this.fieldMetadataRepository.findOneBy({ - id: fieldMetadata.relationTargetFieldMetadataId, - }); - - if (targetFieldMetadata) { - await this.relationMetadataRepository.delete({ - fromFieldMetadataId: In([fieldMetadata.id, targetFieldMetadata.id]), - }); - await this.relationMetadataRepository.delete({ - toFieldMetadataId: In([fieldMetadata.id, targetFieldMetadata.id]), - }); - await fieldMetadataRepository.delete({ - id: In([fieldMetadata.id, targetFieldMetadata.id]), - }); - - await this.workspaceMigrationService.createCustomMigration( - generateMigrationName(`delete-${fieldMetadata.name}`), - workspaceId, - [ - { - name: computeObjectTargetTable(objectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.DROP, - columnName: isManyToOneRelation - ? `${(fieldMetadata as FieldMetadataEntity).settings?.joinColumnName}` - : `${(targetFieldMetadata as FieldMetadataEntity).settings?.joinColumnName}`, - } satisfies WorkspaceMigrationColumnDrop, - ], - } satisfies WorkspaceMigrationTableAction, - ], + if (!isDefined(fieldMetadata.relationTargetFieldMetadata)) { + throw new FieldMetadataException( + 'Target field metadata does not exist', + FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, ); } + + // TODO: remove this once we have deleted the relation metadata table + await this.relationMetadataRepository.delete({ + fromFieldMetadataId: In([ + fieldMetadata.id, + fieldMetadata.relationTargetFieldMetadata.id, + ]), + }); + await this.relationMetadataRepository.delete({ + toFieldMetadataId: In([ + fieldMetadata.id, + fieldMetadata.relationTargetFieldMetadata.id, + ]), + }); + + await fieldMetadataRepository.delete({ + id: In([ + fieldMetadata.id, + fieldMetadata.relationTargetFieldMetadata.id, + ]), + }); + + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName(`delete-${fieldMetadata.name}`), + workspaceId, + [ + { + name: isManyToOneRelation + ? computeObjectTargetTable(fieldMetadata.object) + : computeObjectTargetTable( + fieldMetadata.relationTargetObjectMetadata, + ), + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.DROP, + columnName: isManyToOneRelation + ? `${(fieldMetadata as FieldMetadataEntity).settings?.joinColumnName}` + : `${(fieldMetadata.relationTargetFieldMetadata as FieldMetadataEntity).settings?.joinColumnName}`, + } satisfies WorkspaceMigrationColumnDrop, + ], + } satisfies WorkspaceMigrationTableAction, + ], + ); } else if (isCompositeFieldMetadataType(fieldMetadata.type)) { await fieldMetadataRepository.delete(fieldMetadata.id); const compositeType = compositeTypeDefinitions.get(fieldMetadata.type); @@ -411,7 +425,7 @@ export class FieldMetadataService extends TypeOrmQueryService { return { @@ -432,7 +446,7 @@ export class FieldMetadataService extends TypeOrmQueryService