Rename enum types when tables are renamed (#8794)

## Context
Enum are named after this pattern
`${schema}_${tableName}_${columnName}_enum` however now that we allowed
table name update, we need to make sure their enums are renamed as well.
This commit is contained in:
Weiko
2024-11-28 15:39:20 +01:00
committed by GitHub
parent fbe042db3b
commit 75f5afb968
5 changed files with 185 additions and 5 deletions

View File

@ -0,0 +1,101 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DataSource, QueryRunner, TableColumn } from 'typeorm';
import {
WorkspaceMigrationColumnActionType,
WorkspaceMigrationColumnAlter,
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { WorkspaceMigrationEnumService } from 'src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service';
describe('WorkspaceMigrationEnumService', () => {
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>(
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',
}),
);
});
});
});

View File

@ -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<string> {
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;
}
}