fix: add workspace command to backfill missing AGENT source enum values (#22593)
**What** Adds a 2.19 workspace upgrade command that backfills missing FieldActorSource enum values (AGENT) into the Postgres enums backing every ACTOR composite field (createdBy, updatedBy) across all existing workspaces. Each ACTOR field stores its source sub-field as a Postgres enum scoped to its own table and schema (e.g. workspace_abc.company_createdBySource_enum). Workspaces created before these enum values were introduced are missing them, which causes runtime errors when those sources are used. **How** buildActorSourceEnumBackfillTargets collects all ACTOR fields from the workspace metadata cache and maps each enum sub-property to its (tableName, columnName, enumName, expectedValues) tuple. Before iterating over all targets, the command performs a single fast pg_catalog.pg_enum lookup on company.createdBySource as a representative sentinel. If AGENT is already present there, the workspace is skipped entirely (idempotency fast-path). For each remaining target, ALTER TYPE … ADD VALUE IF NOT EXISTS is issued per missing value via WorkspaceSchemaEnumManagerService.addEnumValue, making the command fully idempotent and safe to re-run. Fixes https://discord.com/channels/1130383047699738754/1522507190949118003 <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22593?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+31
@@ -32,6 +32,37 @@ describe('WorkspaceSchemaEnumManagerService', () => {
|
||||
>;
|
||||
});
|
||||
|
||||
describe('addEnumValue', () => {
|
||||
it('emits a plain ADD VALUE statement', async () => {
|
||||
await service.addEnumValue({
|
||||
queryRunner: queryRunner as unknown as QueryRunner,
|
||||
schemaName: 'workspace_adhj7eaegq93fzpgbfpdm8ok3',
|
||||
enumName: 'company_createdBySource_enum',
|
||||
value: 'AGENT',
|
||||
});
|
||||
|
||||
expect(executedSql).toHaveLength(1);
|
||||
expect(executedSql[0]).toContain('ADD VALUE ');
|
||||
expect(executedSql[0]).not.toContain('IF NOT EXISTS');
|
||||
expect(executedSql[0]).toContain("'AGENT'");
|
||||
});
|
||||
});
|
||||
|
||||
describe('upsertEnumValue', () => {
|
||||
it('emits ADD VALUE IF NOT EXISTS', async () => {
|
||||
await service.upsertEnumValue({
|
||||
queryRunner: queryRunner as unknown as QueryRunner,
|
||||
schemaName: 'workspace_adhj7eaegq93fzpgbfpdm8ok3',
|
||||
enumName: 'company_createdBySource_enum',
|
||||
value: 'AGENT',
|
||||
});
|
||||
|
||||
expect(executedSql).toHaveLength(1);
|
||||
expect(executedSql[0]).toContain('ADD VALUE IF NOT EXISTS');
|
||||
expect(executedSql[0]).toContain("'AGENT'");
|
||||
});
|
||||
});
|
||||
|
||||
describe('alterEnumValues', () => {
|
||||
it('should not generate an enum rename whose target collides with the source when the name exceeds the identifier length limit', async () => {
|
||||
// Real-world case: long object + field names produce an enum name over
|
||||
|
||||
+16
@@ -109,6 +109,22 @@ export class WorkspaceSchemaEnumManagerService {
|
||||
await queryRunner.query(sql);
|
||||
}
|
||||
|
||||
async upsertEnumValue({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
enumName,
|
||||
value,
|
||||
}: {
|
||||
queryRunner: QueryRunner;
|
||||
schemaName: string;
|
||||
enumName: string;
|
||||
value: string;
|
||||
}): Promise<void> {
|
||||
const sql = `ALTER TYPE ${escapeIdentifier(schemaName)}.${escapeIdentifier(enumName)} ADD VALUE IF NOT EXISTS ${escapeLiteral(value)}`;
|
||||
|
||||
await queryRunner.query(sql);
|
||||
}
|
||||
|
||||
async renameEnumValue({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
|
||||
Reference in New Issue
Block a user