From 3f5efdbabc0a2d72bac361d8a9ffc01f95a2f14e Mon Sep 17 00:00:00 2001 From: Weiko Date: Thu, 23 Oct 2025 16:23:34 +0200 Subject: [PATCH] Fix defaultValue with enum options update in migration v2 (#15286) ## Context When updating both enum options and defaultValue, the old default might not be in the new options (or vice versa), causing PostgreSQL constraint violations regardless of update order. ## Solution Sort updates to process defaultValue last; before updating options, temporarily set the new defaultValue in metadata so alterEnumValues creates the column with the correct default, then skip the redundant defaultValue update handler. --- .../update-field-action-handler.service.ts | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service.ts index 4c43229c89..d2306d9f49 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/field/services/update-field-action-handler.service.ts @@ -27,6 +27,7 @@ import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/works import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service'; import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util'; import { PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; +import { findFlatEntityPropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/utils/find-flat-entity-property-update.util'; import { isPropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/utils/is-property-update.util'; import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/types/workspace-migration-field-action-v2'; import { serializeDefaultValueV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/serialize-default-value-v2.util'; @@ -147,7 +148,20 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct let optimisticFlatFieldMetadata = structuredClone(currentFlatFieldMetadata); - for (const update of updates) { + const defaultValueUpdate = findFlatEntityPropertyUpdate({ + flatEntityUpdates: updates, + property: 'defaultValue', + }); + const hasDefaultValueUpdate = isDefined(defaultValueUpdate); + + let wasDefaultValueHandledByEnumUpdate = false; + + const sortedUpdatesWithDefaultValuesUpdateLast = [...updates].sort( + (a, b) => + +(a.property === 'defaultValue') - +(b.property === 'defaultValue'), + ); + + for (const update of sortedUpdatesWithDefaultValuesUpdateLast) { if (isPropertyUpdate(update, 'name')) { await this.handleFieldNameUpdate({ queryRunner, @@ -159,19 +173,31 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct optimisticFlatFieldMetadata.name = update.to; } if (isPropertyUpdate(update, 'defaultValue')) { - await this.handleFieldDefaultValueUpdate({ - queryRunner, - schemaName, - tableName, - flatFieldMetadata: optimisticFlatFieldMetadata, - update, - }); - optimisticFlatFieldMetadata.defaultValue = update.to; + if (wasDefaultValueHandledByEnumUpdate) { + optimisticFlatFieldMetadata.defaultValue = update.to; + } else { + await this.handleFieldDefaultValueUpdate({ + queryRunner, + schemaName, + tableName, + flatFieldMetadata: optimisticFlatFieldMetadata, + update, + }); + optimisticFlatFieldMetadata.defaultValue = update.to; + } } if ( isPropertyUpdate(update, 'options') && isEnumFlatFieldMetadata(optimisticFlatFieldMetadata) ) { + if (hasDefaultValueUpdate) { + optimisticFlatFieldMetadata = { + ...optimisticFlatFieldMetadata, + defaultValue: defaultValueUpdate.to, + }; + wasDefaultValueHandledByEnumUpdate = true; + } + await this.handleFieldOptionsUpdate({ queryRunner, schemaName,