diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts index cd5c8e377..10e302070 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts @@ -443,14 +443,17 @@ export class ObjectMetadataService extends TypeOrmQueryService { + let service: WorkspaceMigrationEnumService; + let queryRunner: QueryRunner; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + WorkspaceMigrationEnumService, + { + provide: DataSource, + useValue: { + createQueryRunner: () => ({ + query: jest.fn(), + addColumn: jest.fn(), + }), + }, + }, + ], + }).compile(); + + service = module.get( + WorkspaceMigrationEnumService, + ); + queryRunner = module.get(DataSource).createQueryRunner(); + }); + + describe('alterEnum', () => { + it('should handle enum column alteration with renamed values', async () => { + const mockMigrationColumn: WorkspaceMigrationColumnAlter = { + action: WorkspaceMigrationColumnActionType.ALTER, + currentColumnDefinition: { + columnName: 'status', + columnType: 'enum', + enum: ['ACTIVE', 'INACTIVE'], + isNullable: false, + defaultValue: 'ACTIVE', + }, + alteredColumnDefinition: { + columnName: 'status', + columnType: 'enum', + enum: [ + { from: 'ACTIVE', to: 'ENABLED' }, + { from: 'INACTIVE', to: 'DISABLED' }, + ], + isNullable: false, + defaultValue: 'ENABLED', + }, + }; + + jest.spyOn(queryRunner, 'query').mockImplementation((query: string) => { + if (query.includes('information_schema.columns')) { + return Promise.resolve([{ udt_name: 'test_status_enum' }]); + } + if (query.includes('SELECT id')) { + return Promise.resolve([ + { id: '1', status: 'ACTIVE' }, + { id: '2', status: 'INACTIVE' }, + ]); + } + + return Promise.resolve(); + }); + + await service.alterEnum( + queryRunner, + 'test_schema', + 'test_table', + mockMigrationColumn, + ); + + expect(queryRunner.query).toHaveBeenCalledWith( + expect.stringContaining('information_schema.columns'), + ['test_schema', 'test_table', 'status'], + ); + expect(queryRunner.query).toHaveBeenCalledWith( + expect.stringContaining('ALTER TYPE'), + ); + expect(queryRunner.addColumn).toHaveBeenCalledWith( + 'test_schema.test_table', + new TableColumn({ + name: 'status', + type: 'enum', + enum: ['ENABLED', 'DISABLED'], + isNullable: false, + default: 'ENABLED', + enumName: 'test_table_status_enum', + }), + ); + }); + }); +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service.ts index 5f5834da7..6a2deb6ff 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service.ts @@ -10,6 +10,10 @@ import { WorkspaceMigrationColumnAlter, WorkspaceMigrationRenamedEnum, } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; +import { + WorkspaceMigrationException, + WorkspaceMigrationExceptionCode, +} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.exception'; @Injectable() export class WorkspaceMigrationEnumService { @@ -33,8 +37,14 @@ export class WorkspaceMigrationEnumService { ); } + const oldEnumTypeName = await this.getEnumTypeName( + queryRunner, + schemaName, + tableName, + migrationColumn.currentColumnDefinition.columnName, + ); + const columnDefinition = migrationColumn.alteredColumnDefinition; - const oldEnumTypeName = `${tableName}_${migrationColumn.currentColumnDefinition.columnName}_enum`; const tempEnumTypeName = `${oldEnumTypeName}_temp`; const newEnumTypeName = `${tableName}_${columnDefinition.columnName}_enum`; const enumValues = @@ -214,4 +224,27 @@ export class WorkspaceMigrationEnumService { RENAME TO "${newEnumTypeName}" `); } + + private async getEnumTypeName( + queryRunner: QueryRunner, + schemaName: string, + tableName: string, + columnName: string, + ): Promise { + const result = await queryRunner.query( + `SELECT udt_name FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND column_name = $3`, + [schemaName, tableName, columnName], + ); + + const enumTypeName = result[0].udt_name; + + if (!enumTypeName) { + throw new WorkspaceMigrationException( + `Enum type name not found for column ${columnName} in table ${tableName} while trying to alter enum`, + WorkspaceMigrationExceptionCode.ENUM_TYPE_NAME_NOT_FOUND, + ); + } + + return enumTypeName; + } }