Upgrade command remove duplicated role target (#16281)
# Introduction
On production facing a migration error with
UpdateRoleTargetsUniqueConstraint1764329720503
```ts
Migration "UpdateRoleTargetsUniqueConstraint1764329720503" failed, error: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
query: ROLLBACK
Error during migration run:
QueryFailedError: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
at PostgresQueryRunner.query (/Users/paulrastoin/ws/twenty/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:219:19)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async UpdateRoleTargetsUniqueConstraint1764329720503.up (/Users/paulrastoin/ws/twenty/packages/twenty-server/dist/database/typeorm/core/migrations/common/1764329720503-update-role-targets-unique-constraint.js:15:9)
at async MigrationExecutor.executePendingMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/migration/MigrationExecutor.js:225:17)
at async DataSource.runMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/data-source/DataSource.js:265:35)
at async Object.handler (/Users/paulrastoin/ws/twenty/node_modules/typeorm/commands/MigrationRunCommand.js:68:13) {
query: 'ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_AGENT" UNIQUE ("workspaceId", "agentId")',
parameters: undefined,
driverError: error: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
at /Users/paulrastoin/ws/twenty/node_modules/pg/lib/client.js:526:17
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async PostgresQueryRunner.query (/Users/paulrastoin/ws/twenty/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:184:25)
at async UpdateRoleTargetsUniqueConstraint1764329720503.up (/Users/paulrastoin/ws/twenty/packages/twenty-server/dist/database/typeorm/core/migrations/common/1764329720503-update-role-targets-unique-constraint.js:15:9)
at async MigrationExecutor.executePendingMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/migration/MigrationExecutor.js:225:17)
at async DataSource.runMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/data-source/DataSource.js:265:35)
at async Object.handler (/Users/paulrastoin/ws/twenty/node_modules/typeorm/commands/MigrationRunCommand.js:68:13) {
length: 314,
severity: 'ERROR',
code: '23505',
```
As several agent has duplicated role target in database
```sql
SELECT constraint_name, COUNT(*) AS duplicate_groups, SUM(duplicate_count - 1) AS rows_to_delete
FROM (
SELECT 'IDX_ROLE_TARGET_UNIQUE_API_KEY' AS constraint_name, COUNT(*) AS duplicate_count
FROM "core"."roleTargets" rt
WHERE rt."apiKeyId" IS NOT NULL
GROUP BY rt."workspaceId", rt."apiKeyId"
HAVING COUNT(*) > 1
UNION ALL
SELECT 'IDX_ROLE_TARGET_UNIQUE_AGENT', COUNT(*)
FROM "core"."roleTargets" rt
WHERE rt."agentId" IS NOT NULL
GROUP BY rt."workspaceId", rt."agentId"
HAVING COUNT(*) > 1
UNION ALL
SELECT 'IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE', COUNT(*)
FROM "core"."roleTargets" rt
WHERE rt."userWorkspaceId" IS NOT NULL
GROUP BY rt."workspaceId", rt."userWorkspaceId"
HAVING COUNT(*) > 1
) AS all_duplicates
GROUP BY constraint_name;
```
with constraint name, duplicated_groups, row_to_delete
`IDX_ROLE_TARGET_UNIQUE_AGENT 2507 7229`
Please note that only active or suspended workspaces contains duplicated
role target
## Fix
Introduced an upgrade command that will only keep the latest inserted
role target
Swallowing migration error on typeorm atomic migration ( still required
for self host new instances etc )
```ts
[Nest] 91886 - 12/03/2025, 2:56:28 PM LOG [DeduplicateRoleTargetsCommand] Running command on workspace SOME_WORKSPACE_ID 2587/2587
flatFieldMetadataMaps,flatIndexMaps,flatObjectMetadataMaps out of 298
query: SELECT version();
[Nest] 91886 - 12/03/2025, 2:56:29 PM LOG [DeduplicateRoleTargetsCommand] Command completed!
```
## Test
Tested through an extract in local, tested both the upgrade command and
the swallowed migration
test
This commit is contained in:
+129
@@ -0,0 +1,129 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { In, type Repository } from 'typeorm';
|
||||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
type DuplicateKey = 'apiKeyId' | 'agentId' | 'userWorkspaceId';
|
||||
|
||||
type DuplicateGroup = {
|
||||
foreignKeyId: string;
|
||||
duplicateKey: DuplicateKey;
|
||||
};
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-13:deduplicate-role-targets',
|
||||
description:
|
||||
'Remove duplicate roleTargets keeping only the most recently updated one for each unique constraint',
|
||||
})
|
||||
export class DeduplicateRoleTargetsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(RoleTargetEntity)
|
||||
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
options,
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options.dryRun || false;
|
||||
|
||||
const duplicateGroups =
|
||||
await this.findDuplicateGroupsForWorkspace(workspaceId);
|
||||
|
||||
if (duplicateGroups.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idsToDelete: string[] = [];
|
||||
|
||||
for (const duplicateGroup of duplicateGroups) {
|
||||
const duplicateIds = await this.findDuplicateIdsToDelete(
|
||||
workspaceId,
|
||||
duplicateGroup,
|
||||
);
|
||||
|
||||
idsToDelete.push(...duplicateIds);
|
||||
}
|
||||
|
||||
if (idsToDelete.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
this.logger.log(
|
||||
`DRY RUN: Would delete ${idsToDelete.length} duplicate roleTarget(s)`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.roleTargetRepository.delete({ id: In(idsToDelete) });
|
||||
|
||||
this.logger.log(`Deleted ${idsToDelete.length} duplicate roleTarget(s)`);
|
||||
}
|
||||
|
||||
private async findDuplicateGroupsForWorkspace(
|
||||
workspaceId: string,
|
||||
): Promise<DuplicateGroup[]> {
|
||||
const duplicateGroups: DuplicateGroup[] = [];
|
||||
|
||||
const duplicateKeys: DuplicateKey[] = [
|
||||
'apiKeyId',
|
||||
'agentId',
|
||||
'userWorkspaceId',
|
||||
];
|
||||
|
||||
for (const duplicateKey of duplicateKeys) {
|
||||
const duplicates = await this.roleTargetRepository
|
||||
.createQueryBuilder('roleTarget')
|
||||
.select([`roleTarget.${duplicateKey} AS "foreignKeyId"`])
|
||||
.where('roleTarget.workspaceId = :workspaceId', { workspaceId })
|
||||
.andWhere(`roleTarget.${duplicateKey} IS NOT NULL`)
|
||||
.groupBy(`roleTarget.${duplicateKey}`)
|
||||
.having('COUNT(*) > 1')
|
||||
.getRawMany<{ foreignKeyId: string }>();
|
||||
|
||||
for (const duplicate of duplicates) {
|
||||
duplicateGroups.push({
|
||||
foreignKeyId: duplicate.foreignKeyId,
|
||||
duplicateKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return duplicateGroups;
|
||||
}
|
||||
|
||||
private async findDuplicateIdsToDelete(
|
||||
workspaceId: string,
|
||||
duplicateGroup: DuplicateGroup,
|
||||
): Promise<string[]> {
|
||||
const { foreignKeyId, duplicateKey } = duplicateGroup;
|
||||
|
||||
const roleTargets = await this.roleTargetRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
[duplicateKey]: foreignKeyId,
|
||||
},
|
||||
order: {
|
||||
updatedAt: 'DESC',
|
||||
},
|
||||
});
|
||||
|
||||
// Keep the first one (most recently updated), delete the rest
|
||||
return roleTargets.slice(1).map((roleTarget) => roleTarget.id);
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-13:update-role-targets-unique-constraint-migration',
|
||||
description:
|
||||
'Update roleTargets unique constraints from combined to separate constraints',
|
||||
})
|
||||
export class UpdateRoleTargetsUniqueConstraintMigrationCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
private hasRunOnce = false;
|
||||
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
if (this.hasRunOnce) {
|
||||
this.logger.log(
|
||||
'Skipping has already been run once UpdateRoleTargetsUniqueConstraintMigrationCommand',
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
if (!options.dryRun) {
|
||||
try {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_API_KEY" UNIQUE ("workspaceId", "apiKeyId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_AGENT" UNIQUE ("workspaceId", "agentId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE" UNIQUE ("workspaceId", "userWorkspaceId")`,
|
||||
);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
this.logger.log(
|
||||
'Successfully run UpdateRoleTargetsUniqueConstraintMigrationCommand',
|
||||
);
|
||||
this.hasRunOnce = true;
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.log(
|
||||
`Rollbacking UpdateRoleTargetsUniqueConstraintMigrationCommand: ${error.message}`,
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -3,10 +3,14 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { BackfillViewMainGroupByFieldMetadataIdCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-backfill-view-main-group-by-field-metadata-id.command';
|
||||
import { CleanEmptyStringNullInTextFieldsCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-clean-empty-string-null-in-text-fields.command';
|
||||
import { DeduplicateRoleTargetsCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-deduplicate-role-targets.command';
|
||||
import { UpdateRoleTargetsUniqueConstraintMigrationCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-update-role-targets-unique-constraint-migration.command';
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
|
||||
@@ -18,16 +22,22 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit
|
||||
FieldMetadataEntity,
|
||||
ViewEntity,
|
||||
ViewGroupEntity,
|
||||
FeatureFlagEntity,
|
||||
RoleTargetEntity,
|
||||
]),
|
||||
DataSourceModule,
|
||||
],
|
||||
providers: [
|
||||
CleanEmptyStringNullInTextFieldsCommand,
|
||||
BackfillViewMainGroupByFieldMetadataIdCommand,
|
||||
DeduplicateRoleTargetsCommand,
|
||||
UpdateRoleTargetsUniqueConstraintMigrationCommand,
|
||||
],
|
||||
exports: [
|
||||
CleanEmptyStringNullInTextFieldsCommand,
|
||||
BackfillViewMainGroupByFieldMetadataIdCommand,
|
||||
DeduplicateRoleTargetsCommand,
|
||||
UpdateRoleTargetsUniqueConstraintMigrationCommand,
|
||||
],
|
||||
})
|
||||
export class V1_13_UpgradeVersionCommandModule {}
|
||||
|
||||
+15
@@ -27,6 +27,8 @@ import { CleanNullEquivalentValuesCommand } from 'src/database/commands/upgrade-
|
||||
import { CreateWorkspaceCustomApplicationCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-create-workspace-custom-application.command';
|
||||
import { SetStandardApplicationNotUninstallableCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-set-standard-application-not-uninstallable.command';
|
||||
import { WorkspaceCustomApplicationIdNonNullableCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-workspace-custom-application-id-non-nullable-migration.command';
|
||||
import { DeduplicateRoleTargetsCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-deduplicate-role-targets.command';
|
||||
import { UpdateRoleTargetsUniqueConstraintMigrationCommand } from 'src/database/commands/upgrade-version-command/1-13/1-13-update-role-targets-unique-constraint-migration.command';
|
||||
import { FixLabelIdentifierPositionAndVisibilityCommand } from 'src/database/commands/upgrade-version-command/1-6/1-6-fix-label-identifier-position-and-visibility.command';
|
||||
import { BackfillWorkflowManualTriggerAvailabilityCommand } from 'src/database/commands/upgrade-version-command/1-7/1-7-backfill-workflow-manual-trigger-availability.command';
|
||||
import { DeduplicateUniqueFieldsCommand } from 'src/database/commands/upgrade-version-command/1-8/1-8-deduplicate-unique-fields.command';
|
||||
@@ -92,6 +94,10 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly addMessagesImportScheduledSyncStageCommand: AddMessagesImportScheduledSyncStageCommand,
|
||||
protected readonly addCalendarEventsImportScheduledSyncStageCommand: AddCalendarEventsImportScheduledSyncStageCommand,
|
||||
protected readonly cleanNullEquivalentValuesCommand: CleanNullEquivalentValuesCommand,
|
||||
|
||||
// 1.13 Commands
|
||||
protected readonly deduplicateRoleTargetsCommand: DeduplicateRoleTargetsCommand,
|
||||
protected readonly updateRoleTargetsUniqueConstraintMigrationCommand: UpdateRoleTargetsUniqueConstraintMigrationCommand,
|
||||
) {
|
||||
super(
|
||||
workspaceRepository,
|
||||
@@ -159,6 +165,14 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
afterSyncMetadata: [this.setStandardApplicationNotUninstallableCommand],
|
||||
};
|
||||
|
||||
const commands_1130: VersionCommands = {
|
||||
beforeSyncMetadata: [
|
||||
this.deduplicateRoleTargetsCommand,
|
||||
this.updateRoleTargetsUniqueConstraintMigrationCommand,
|
||||
],
|
||||
afterSyncMetadata: [],
|
||||
};
|
||||
|
||||
this.allCommands = {
|
||||
'1.6.0': commands_160,
|
||||
'1.7.0': commands_170,
|
||||
@@ -166,6 +180,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
'1.10.0': commands_1100,
|
||||
'1.11.0': commands_1110,
|
||||
'1.12.0': commands_1120,
|
||||
'1.13.0': commands_1130,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+41
-15
@@ -6,29 +6,55 @@ export class UpdateRoleTargetsUniqueConstraint1764329720503
|
||||
name = 'UpdateRoleTargetsUniqueConstraint1764329720503';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_API_KEY" UNIQUE ("workspaceId", "apiKeyId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_AGENT" UNIQUE ("workspaceId", "agentId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_USER_WORKSPACE" UNIQUE ("workspaceId", "userWorkspaceId")`,
|
||||
);
|
||||
const savepointName = 'sp_update_role_targets_unique_constraint';
|
||||
|
||||
try {
|
||||
await queryRunner.query(`SAVEPOINT ${savepointName}`);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_API_KEY" UNIQUE ("workspaceId", "apiKeyId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_AGENT" UNIQUE ("workspaceId", "agentId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE" UNIQUE ("workspaceId", "userWorkspaceId")`,
|
||||
);
|
||||
|
||||
await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`);
|
||||
} catch (e) {
|
||||
try {
|
||||
await queryRunner.query(`ROLLBACK TO SAVEPOINT ${savepointName}`);
|
||||
await queryRunner.query(`RELEASE SAVEPOINT ${savepointName}`);
|
||||
} catch (rollbackError) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
'Failed to rollback to savepoint in UpdateRoleTargetsUniqueConstraint1764329720503',
|
||||
rollbackError,
|
||||
);
|
||||
throw rollbackError;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
'Swallowing UpdateRoleTargetsUniqueConstraint1764329720503 error',
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_USER_WORKSPACE"`,
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_AGENT"`,
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_AGENT"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_API_KEY"`,
|
||||
`ALTER TABLE "core"."roleTargets" DROP CONSTRAINT "IDX_ROLE_TARGET_UNIQUE_API_KEY"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE" UNIQUE ("workspaceId", "userWorkspaceId", "agentId", "apiKeyId")`,
|
||||
|
||||
-11
@@ -9,17 +9,6 @@ export class RenameRoleTargets1764671363647 implements MigrationInterface {
|
||||
`ALTER TABLE "core"."roleTargets" RENAME TO "roleTarget"`,
|
||||
);
|
||||
|
||||
// Rename unique constraints
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" RENAME CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_USER_WORKSPACE" TO "IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" RENAME CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_AGENT" TO "IDX_ROLE_TARGET_UNIQUE_AGENT"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" RENAME CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_API_KEY" TO "IDX_ROLE_TARGET_UNIQUE_API_KEY"`,
|
||||
);
|
||||
|
||||
// Rename check constraint
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."roleTarget" RENAME CONSTRAINT "CHK_role_targets_single_entity" TO "CHK_role_target_single_entity"`,
|
||||
|
||||
Reference in New Issue
Block a user