add workspaceId to indirect entities (#19522)

Required for `workspace:export` command

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
neo773
2026-04-10 01:00:28 +05:30
committed by GitHub
parent 7ef80dd238
commit 8a10071253
38 changed files with 439 additions and 15 deletions
@@ -4,7 +4,9 @@ import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decor
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
@RegisteredInstanceCommand('1.22.0', 1775749486425)
export class AutoGeneratedFastInstanceCommand implements FastInstanceCommand {
export class AddPermissionFlagRoleIdIndexFastInstanceCommand
implements FastInstanceCommand
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE INDEX "IDX_PERMISSION_FLAG_ROLE_ID" ON "core"."permissionFlag" ("roleId") ',
@@ -0,0 +1,36 @@
import { QueryRunner } from 'typeorm';
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
const TABLES = [
'applicationVariable',
'indexFieldMetadata',
'twoFactorAuthenticationMethod',
'agentMessagePart',
'agentTurnEvaluation',
'agentChatThread',
'agentTurn',
'agentMessage',
];
@RegisteredInstanceCommand('1.22.0', 1775758621017)
export class AddWorkspaceIdToIndirectEntitiesFastInstanceCommand
implements FastInstanceCommand
{
public async up(queryRunner: QueryRunner): Promise<void> {
for (const table of TABLES) {
await queryRunner.query(
`ALTER TABLE "core"."${table}" ADD "workspaceId" uuid`,
);
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
for (const table of TABLES) {
await queryRunner.query(
`ALTER TABLE "core"."${table}" DROP COLUMN "workspaceId"`,
);
}
}
}
@@ -0,0 +1,111 @@
import { QueryRunner } from 'typeorm';
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
@RegisteredInstanceCommand('1.22.0', 1775761294897)
export class AddWorkspaceIdIndexesAndFksFastInstanceCommand
implements FastInstanceCommand
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE INDEX "IDX_78ae6cfe5f49a76c4bf842ad58" ON "core"."applicationVariable" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_d8cf7f15cf6466ac0e3b443b3d" ON "core"."indexFieldMetadata" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_b8282d1e10fbb7856950f86c61" ON "core"."twoFactorAuthenticationMethod" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_70b398dc45219db8f3e36b3a07" ON "core"."agentMessagePart" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_c81d8fabdda94b7fa86fb6f1e7" ON "core"."agentTurnEvaluation" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_3d097ed53841d80904ed02c837" ON "core"."agentChatThread" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_a4bb3c6176c2607693a6756ff6" ON "core"."agentTurn" ("workspaceId") ',
);
await queryRunner.query(
'CREATE INDEX "IDX_75db4f2e80922078e8171ae130" ON "core"."agentMessage" ("workspaceId") ',
);
await queryRunner.query(
'ALTER TABLE "core"."applicationVariable" ADD CONSTRAINT "FK_78ae6cfe5f49a76c4bf842ad58b" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."indexFieldMetadata" ADD CONSTRAINT "FK_d8cf7f15cf6466ac0e3b443b3d2" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."twoFactorAuthenticationMethod" ADD CONSTRAINT "FK_b8282d1e10fbb7856950f86c616" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."agentMessagePart" ADD CONSTRAINT "FK_70b398dc45219db8f3e36b3a078" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."agentTurnEvaluation" ADD CONSTRAINT "FK_c81d8fabdda94b7fa86fb6f1e70" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."agentChatThread" ADD CONSTRAINT "FK_3d097ed53841d80904ed02c8373" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."agentTurn" ADD CONSTRAINT "FK_a4bb3c6176c2607693a6756ff6c" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
await queryRunner.query(
'ALTER TABLE "core"."agentMessage" ADD CONSTRAINT "FK_75db4f2e80922078e8171ae130a" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE "core"."agentMessage" DROP CONSTRAINT "FK_75db4f2e80922078e8171ae130a"',
);
await queryRunner.query(
'ALTER TABLE "core"."agentTurn" DROP CONSTRAINT "FK_a4bb3c6176c2607693a6756ff6c"',
);
await queryRunner.query(
'ALTER TABLE "core"."agentChatThread" DROP CONSTRAINT "FK_3d097ed53841d80904ed02c8373"',
);
await queryRunner.query(
'ALTER TABLE "core"."agentTurnEvaluation" DROP CONSTRAINT "FK_c81d8fabdda94b7fa86fb6f1e70"',
);
await queryRunner.query(
'ALTER TABLE "core"."agentMessagePart" DROP CONSTRAINT "FK_70b398dc45219db8f3e36b3a078"',
);
await queryRunner.query(
'ALTER TABLE "core"."twoFactorAuthenticationMethod" DROP CONSTRAINT "FK_b8282d1e10fbb7856950f86c616"',
);
await queryRunner.query(
'ALTER TABLE "core"."indexFieldMetadata" DROP CONSTRAINT "FK_d8cf7f15cf6466ac0e3b443b3d2"',
);
await queryRunner.query(
'ALTER TABLE "core"."applicationVariable" DROP CONSTRAINT "FK_78ae6cfe5f49a76c4bf842ad58b"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_75db4f2e80922078e8171ae130"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_a4bb3c6176c2607693a6756ff6"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_3d097ed53841d80904ed02c837"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_c81d8fabdda94b7fa86fb6f1e7"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_70b398dc45219db8f3e36b3a07"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_b8282d1e10fbb7856950f86c61"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_d8cf7f15cf6466ac0e3b443b3d"',
);
await queryRunner.query(
'DROP INDEX "core"."IDX_78ae6cfe5f49a76c4bf842ad58"',
);
}
}
@@ -0,0 +1,89 @@
import { DataSource, QueryRunner } from 'typeorm';
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
import { SlowInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/slow-instance-command.interface';
type BackfillDefinition = {
table: string;
parentTable: string;
foreignKey: string;
};
// Order matters: parents must be backfilled before children
const BACKFILL_DEFINITIONS: BackfillDefinition[] = [
{
table: 'twoFactorAuthenticationMethod',
parentTable: 'userWorkspace',
foreignKey: 'userWorkspaceId',
},
{
table: 'agentChatThread',
parentTable: 'userWorkspace',
foreignKey: 'userWorkspaceId',
},
{
table: 'agentTurn',
parentTable: 'agentChatThread',
foreignKey: 'threadId',
},
{
table: 'agentMessage',
parentTable: 'agentChatThread',
foreignKey: 'threadId',
},
{
table: 'agentTurnEvaluation',
parentTable: 'agentTurn',
foreignKey: 'turnId',
},
{
table: 'agentMessagePart',
parentTable: 'agentMessage',
foreignKey: 'messageId',
},
{
table: 'indexFieldMetadata',
parentTable: 'indexMetadata',
foreignKey: 'indexMetadataId',
},
{
table: 'applicationVariable',
parentTable: 'application',
foreignKey: 'applicationId',
},
];
const TABLES = BACKFILL_DEFINITIONS.map((definition) => definition.table);
@RegisteredInstanceCommand('1.22.0', 1775758621018, { type: 'slow' })
export class BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand
implements SlowInstanceCommand
{
async runDataMigration(dataSource: DataSource): Promise<void> {
for (const { table, parentTable, foreignKey } of BACKFILL_DEFINITIONS) {
await dataSource.query(
`UPDATE "core"."${table}" t
SET "workspaceId" = p."workspaceId"
FROM "core"."${parentTable}" p
WHERE t."${foreignKey}" = p."id"
AND t."workspaceId" IS NULL`,
);
}
}
public async up(queryRunner: QueryRunner): Promise<void> {
for (const table of TABLES) {
await queryRunner.query(
`ALTER TABLE "core"."${table}" ALTER COLUMN "workspaceId" SET NOT NULL`,
);
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
for (const table of TABLES) {
await queryRunner.query(
`ALTER TABLE "core"."${table}" ALTER COLUMN "workspaceId" DROP NOT NULL`,
);
}
}
}
@@ -3,11 +3,17 @@
import { AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-21/1-21-instance-command-fast-1775129420309-add-view-field-group-id-index-on-view-field';
import { MigrateMessagingCalendarToCoreFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-21/1-21-instance-command-fast-1775165049548-migrate-messaging-calendar-to-core';
import { AddEmailThreadWidgetTypeFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-21/1-21-instance-command-fast-1775200000000-add-email-thread-widget-type';
import { AutoGeneratedFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775749486425-auto-generated';
import { AddPermissionFlagRoleIdIndexFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775749486425-add-permission-flag-role-id-index';
import { AddWorkspaceIdToIndirectEntitiesFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775758621017-add-workspace-id-to-indirect-entities';
import { BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-slow-1775758621018-backfill-workspace-id-on-indirect-entities';
import { AddWorkspaceIdIndexesAndFksFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-fast-1775761294897-add-workspace-id-indexes-and-fks-to-indirect-entities';
export const INSTANCE_COMMANDS = [
AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand,
MigrateMessagingCalendarToCoreFastInstanceCommand,
AddEmailThreadWidgetTypeFastInstanceCommand,
AutoGeneratedFastInstanceCommand,
AddPermissionFlagRoleIdIndexFastInstanceCommand,
AddWorkspaceIdToIndirectEntitiesFastInstanceCommand,
BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand,
AddWorkspaceIdIndexesAndFksFastInstanceCommand,
];