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
This commit is contained in:
Charles Bochet
2025-05-13 16:22:59 +02:00
committed by GitHub
parent bed33b00b9
commit e94d90894b

View File

@ -318,31 +318,30 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
id: input.id,
workspaceId: workspaceId,
},
relations: [
'object',
'relationTargetFieldMetadata',
'relationTargetObjectMetadata',
],
});
if (!fieldMetadata) {
if (!isDefined(fieldMetadata)) {
throw new FieldMetadataException(
'Field does not exist',
FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND,
);
}
const [objectMetadata] = await this.objectMetadataRepository.find({
where: {
id: fieldMetadata.objectMetadataId,
},
relations: ['fields'],
order: {},
});
if (!objectMetadata) {
if (!isDefined(fieldMetadata.object)) {
throw new FieldMetadataException(
'Object metadata does not exist',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
if (objectMetadata.labelIdentifierFieldMetadataId === fieldMetadata.id) {
if (
fieldMetadata.object.labelIdentifierFieldMetadataId === fieldMetadata.id
) {
throw new FieldMetadataException(
'Cannot delete, please update the label identifier field first',
FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
@ -359,41 +358,56 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
(fieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>)
.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<FieldMetadataType.RELATION>).settings?.joinColumnName}`
: `${(targetFieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).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<FieldMetadataType.RELATION>).settings?.joinColumnName}`
: `${(fieldMetadata.relationTargetFieldMetadata as FieldMetadataEntity<FieldMetadataType.RELATION>).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<FieldMetadataEntit
workspaceId,
[
{
name: computeObjectTargetTable(objectMetadata),
name: computeObjectTargetTable(fieldMetadata.object),
action: WorkspaceMigrationTableActionType.ALTER,
columns: compositeType.properties.map((property) => {
return {
@ -432,7 +446,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
workspaceId,
[
{
name: computeObjectTargetTable(objectMetadata),
name: computeObjectTargetTable(fieldMetadata.object),
action: WorkspaceMigrationTableActionType.ALTER,
columns: [
{