diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000000000-rebuild-unique-phone-indexes.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000000000-rebuild-unique-phone-indexes.command.ts index 9b6cdca5df..c0ad1778e7 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000000000-rebuild-unique-phone-indexes.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/2-5/2-5-workspace-command-1778000000000-rebuild-unique-phone-indexes.command.ts @@ -1,6 +1,7 @@ import { Command } from 'nest-commander'; import { FieldMetadataType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; +import { isNonEmptyString } from '@sniptt/guards'; import { ActiveOrSuspendedWorkspaceCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspace.command-runner'; import { WorkspaceIteratorService } from 'src/database/commands/command-runners/workspace-iterator.service'; @@ -10,13 +11,17 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/ import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; import { + computeFlatIndexFieldColumnNames, createIndexInWorkspaceSchema, dropIndexFromWorkspaceSchema, } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/index/utils/index-action-handler.utils'; import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util'; +const LEGACY_NON_EMPTY_PARTIAL_INDEX_PATTERN = /^"[a-zA-Z][a-zA-Z0-9]*" != ''$/; + @RegisteredWorkspaceCommand('2.5.0', 1778000000000) @Command({ name: 'upgrade:2-5:rebuild-unique-phone-indexes', @@ -103,6 +108,35 @@ export class RebuildUniquePhoneIndexesCommand extends ActiveOrSuspendedWorkspace flatEntityMaps: flatObjectMetadataMaps, }); + const hasLegacyNonEmptyPartialClause = + isNonEmptyString(uniquePhoneIndex.indexWhereClause) && + LEGACY_NON_EMPTY_PARTIAL_INDEX_PATTERN.test( + uniquePhoneIndex.indexWhereClause, + ); + + if (hasLegacyNonEmptyPartialClause) { + const tableName = computeObjectTargetTable(flatObjectMetadata); + const columns = computeFlatIndexFieldColumnNames({ + flatIndexFieldMetadatas: uniquePhoneIndex.flatIndexFieldMetadatas, + flatFieldMetadataMaps, + }); + + for (const column of columns) { + await queryRunner.query( + `UPDATE "${schemaName}"."${tableName}" + SET "${column}" = NULL + WHERE "${column}" = ''`, + ); + } + + await queryRunner.query( + `UPDATE "core"."indexMetadata" + SET "indexWhereClause" = NULL + WHERE id = $1`, + [uniquePhoneIndex.id], + ); + } + await dropIndexFromWorkspaceSchema({ indexName: uniquePhoneIndex.name, workspaceSchemaManagerService: this.workspaceSchemaManagerService, @@ -110,8 +144,13 @@ export class RebuildUniquePhoneIndexesCommand extends ActiveOrSuspendedWorkspace schemaName, }); + const flatIndexMetadataForRebuild: FlatIndexMetadata = + hasLegacyNonEmptyPartialClause + ? { ...uniquePhoneIndex, indexWhereClause: null } + : uniquePhoneIndex; + await createIndexInWorkspaceSchema({ - flatIndexMetadata: uniquePhoneIndex, + flatIndexMetadata: flatIndexMetadataForRebuild, flatObjectMetadata, flatFieldMetadataMaps, workspaceSchemaManagerService: this.workspaceSchemaManagerService, @@ -120,7 +159,7 @@ export class RebuildUniquePhoneIndexesCommand extends ActiveOrSuspendedWorkspace }); this.logger.log( - `Rebuilt unique phone index ${uniquePhoneIndex.name} for workspace ${workspaceId}`, + `Rebuilt unique phone index ${uniquePhoneIndex.name} for workspace ${workspaceId}${hasLegacyNonEmptyPartialClause ? ' (dropped legacy non-empty partial WHERE clause)' : ''}`, ); } await queryRunner.commitTransaction();