mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 12:57:29 -08:00
fix(core): Add missing primary key to execution annotation tags table (#11168)
This commit is contained in:
parent
09954f6b32
commit
b4b543d41d
|
@ -25,7 +25,10 @@ export class CreateAnnotationTables1724753530828 implements ReversibleMigration
|
||||||
.withIndexOn('name', true).withTimestamps;
|
.withIndexOn('name', true).withTimestamps;
|
||||||
|
|
||||||
await createTable(annotationTagMappingsTableName)
|
await createTable(annotationTagMappingsTableName)
|
||||||
.withColumns(column('annotationId').int.notNull, column('tagId').varchar(24).notNull)
|
.withColumns(
|
||||||
|
column('annotationId').int.notNull.primary,
|
||||||
|
column('tagId').varchar(24).notNull.primary,
|
||||||
|
)
|
||||||
.withForeignKey('annotationId', {
|
.withForeignKey('annotationId', {
|
||||||
tableName: annotationsTableName,
|
tableName: annotationsTableName,
|
||||||
columnName: 'id',
|
columnName: 'id',
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import assert from 'node:assert';
|
||||||
|
|
||||||
|
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
|
||||||
|
|
||||||
|
export class AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644
|
||||||
|
implements IrreversibleMigration
|
||||||
|
{
|
||||||
|
async up({ queryRunner, tablePrefix }: MigrationContext) {
|
||||||
|
// Check if the primary key already exists
|
||||||
|
const table = await queryRunner.getTable(`${tablePrefix}execution_annotation_tags`);
|
||||||
|
|
||||||
|
assert(table, 'execution_annotation_tags table not found');
|
||||||
|
|
||||||
|
const hasPrimaryKey = table.primaryColumns.length > 0;
|
||||||
|
|
||||||
|
if (!hasPrimaryKey) {
|
||||||
|
await queryRunner.createPrimaryKey(`${tablePrefix}execution_annotation_tags`, [
|
||||||
|
'annotationId',
|
||||||
|
'tagId',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ import { CreateAnnotationTables1724753530828 } from '../common/1724753530828-Cre
|
||||||
import { AddApiKeysTable1724951148974 } from '../common/1724951148974-AddApiKeysTable';
|
import { AddApiKeysTable1724951148974 } from '../common/1724951148974-AddApiKeysTable';
|
||||||
import { CreateProcessedDataTable1726606152711 } from '../common/1726606152711-CreateProcessedDataTable';
|
import { CreateProcessedDataTable1726606152711 } from '../common/1726606152711-CreateProcessedDataTable';
|
||||||
import { SeparateExecutionCreationFromStart1727427440136 } from '../common/1727427440136-SeparateExecutionCreationFromStart';
|
import { SeparateExecutionCreationFromStart1727427440136 } from '../common/1727427440136-SeparateExecutionCreationFromStart';
|
||||||
|
import { AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644 } from '../common/1728659839644-AddMissingPrimaryKeyOnAnnotationTagMapping';
|
||||||
|
|
||||||
export const mysqlMigrations: Migration[] = [
|
export const mysqlMigrations: Migration[] = [
|
||||||
InitialMigration1588157391238,
|
InitialMigration1588157391238,
|
||||||
|
@ -134,4 +135,5 @@ export const mysqlMigrations: Migration[] = [
|
||||||
AddApiKeysTable1724951148974,
|
AddApiKeysTable1724951148974,
|
||||||
SeparateExecutionCreationFromStart1727427440136,
|
SeparateExecutionCreationFromStart1727427440136,
|
||||||
CreateProcessedDataTable1726606152711,
|
CreateProcessedDataTable1726606152711,
|
||||||
|
AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644,
|
||||||
];
|
];
|
||||||
|
|
|
@ -66,6 +66,7 @@ import { CreateAnnotationTables1724753530828 } from '../common/1724753530828-Cre
|
||||||
import { AddApiKeysTable1724951148974 } from '../common/1724951148974-AddApiKeysTable';
|
import { AddApiKeysTable1724951148974 } from '../common/1724951148974-AddApiKeysTable';
|
||||||
import { CreateProcessedDataTable1726606152711 } from '../common/1726606152711-CreateProcessedDataTable';
|
import { CreateProcessedDataTable1726606152711 } from '../common/1726606152711-CreateProcessedDataTable';
|
||||||
import { SeparateExecutionCreationFromStart1727427440136 } from '../common/1727427440136-SeparateExecutionCreationFromStart';
|
import { SeparateExecutionCreationFromStart1727427440136 } from '../common/1727427440136-SeparateExecutionCreationFromStart';
|
||||||
|
import { AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644 } from '../common/1728659839644-AddMissingPrimaryKeyOnAnnotationTagMapping';
|
||||||
|
|
||||||
export const postgresMigrations: Migration[] = [
|
export const postgresMigrations: Migration[] = [
|
||||||
InitialMigration1587669153312,
|
InitialMigration1587669153312,
|
||||||
|
@ -134,4 +135,5 @@ export const postgresMigrations: Migration[] = [
|
||||||
AddApiKeysTable1724951148974,
|
AddApiKeysTable1724951148974,
|
||||||
SeparateExecutionCreationFromStart1727427440136,
|
SeparateExecutionCreationFromStart1727427440136,
|
||||||
CreateProcessedDataTable1726606152711,
|
CreateProcessedDataTable1726606152711,
|
||||||
|
AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import assert from 'node:assert';
|
||||||
|
|
||||||
|
import type { IrreversibleMigration, MigrationContext } from '@/databases/types';
|
||||||
|
|
||||||
|
const annotationsTableName = 'execution_annotations';
|
||||||
|
const annotationTagsTableName = 'annotation_tag_entity';
|
||||||
|
const annotationTagMappingsTableName = 'execution_annotation_tags';
|
||||||
|
|
||||||
|
export class AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644
|
||||||
|
implements IrreversibleMigration
|
||||||
|
{
|
||||||
|
async up({
|
||||||
|
queryRunner,
|
||||||
|
tablePrefix,
|
||||||
|
schemaBuilder: { createTable, column, dropIndex },
|
||||||
|
}: MigrationContext) {
|
||||||
|
// Check if the primary key already exists
|
||||||
|
const table = await queryRunner.getTable(`${tablePrefix}execution_annotation_tags`);
|
||||||
|
|
||||||
|
assert(table, 'execution_annotation_tags table not found');
|
||||||
|
|
||||||
|
const hasPrimaryKey = table.primaryColumns.length > 0;
|
||||||
|
|
||||||
|
// Do nothing if the primary key already exists
|
||||||
|
if (hasPrimaryKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SQLite doesn't support adding a primary key to an existing table
|
||||||
|
// So we have to do the following steps:
|
||||||
|
|
||||||
|
// 1. Rename the existing table
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE ${tablePrefix}${annotationTagMappingsTableName} RENAME TO ${tablePrefix}${annotationTagMappingsTableName}_tmp;`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1.1 Drop the existing indices
|
||||||
|
await dropIndex(`${annotationTagMappingsTableName}_tmp`, ['tagId'], {
|
||||||
|
customIndexName: 'IDX_a3697779b366e131b2bbdae297',
|
||||||
|
});
|
||||||
|
await dropIndex(`${annotationTagMappingsTableName}_tmp`, ['annotationId'], {
|
||||||
|
customIndexName: 'IDX_c1519757391996eb06064f0e7c',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Create a new table with the desired structure
|
||||||
|
await createTable(annotationTagMappingsTableName)
|
||||||
|
.withColumns(
|
||||||
|
column('annotationId').int.notNull.primary,
|
||||||
|
column('tagId').varchar(24).notNull.primary,
|
||||||
|
)
|
||||||
|
.withForeignKey('annotationId', {
|
||||||
|
tableName: annotationsTableName,
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
.withIndexOn('tagId')
|
||||||
|
.withIndexOn('annotationId')
|
||||||
|
.withForeignKey('tagId', {
|
||||||
|
tableName: annotationTagsTableName,
|
||||||
|
columnName: 'id',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Copy data from the old table to the new one
|
||||||
|
await queryRunner.query(
|
||||||
|
`INSERT INTO ${tablePrefix}${annotationTagMappingsTableName} SELECT * FROM ${tablePrefix}${annotationTagMappingsTableName}_tmp;`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4. Drop the old table
|
||||||
|
await queryRunner.dropTable(`${tablePrefix}${annotationTagMappingsTableName}_tmp`, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ import { ExecutionSoftDelete1693491613982 } from './1693491613982-ExecutionSoftD
|
||||||
import { DropRoleMapping1705429061930 } from './1705429061930-DropRoleMapping';
|
import { DropRoleMapping1705429061930 } from './1705429061930-DropRoleMapping';
|
||||||
import { AddActivatedAtUserSetting1717498465931 } from './1717498465931-AddActivatedAtUserSetting';
|
import { AddActivatedAtUserSetting1717498465931 } from './1717498465931-AddActivatedAtUserSetting';
|
||||||
import { AddApiKeysTable1724951148974 } from './1724951148974-AddApiKeysTable';
|
import { AddApiKeysTable1724951148974 } from './1724951148974-AddApiKeysTable';
|
||||||
|
import { AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644 } from './1728659839644-AddMissingPrimaryKeyOnAnnotationTagMapping';
|
||||||
import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames';
|
import { UniqueWorkflowNames1620821879465 } from '../common/1620821879465-UniqueWorkflowNames';
|
||||||
import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials';
|
import { UpdateWorkflowCredentials1630330987096 } from '../common/1630330987096-UpdateWorkflowCredentials';
|
||||||
import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds';
|
import { AddNodeIds1658930531669 } from '../common/1658930531669-AddNodeIds';
|
||||||
|
@ -128,6 +129,7 @@ const sqliteMigrations: Migration[] = [
|
||||||
AddApiKeysTable1724951148974,
|
AddApiKeysTable1724951148974,
|
||||||
SeparateExecutionCreationFromStart1727427440136,
|
SeparateExecutionCreationFromStart1727427440136,
|
||||||
CreateProcessedDataTable1726606152711,
|
CreateProcessedDataTable1726606152711,
|
||||||
|
AddMissingPrimaryKeyOnAnnotationTagMapping1728659839644,
|
||||||
];
|
];
|
||||||
|
|
||||||
export { sqliteMigrations };
|
export { sqliteMigrations };
|
||||||
|
|
|
@ -563,10 +563,10 @@ describe('ExecutionService', () => {
|
||||||
{
|
{
|
||||||
...summaryShape,
|
...summaryShape,
|
||||||
annotation: {
|
annotation: {
|
||||||
tags: [
|
tags: expect.arrayContaining([
|
||||||
expect.objectContaining({ name: 'tag1' }),
|
expect.objectContaining({ name: 'tag1' }),
|
||||||
expect.objectContaining({ name: 'tag2' }),
|
expect.objectContaining({ name: 'tag2' }),
|
||||||
],
|
]),
|
||||||
vote: 'up',
|
vote: 'up',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -646,10 +646,10 @@ describe('ExecutionService', () => {
|
||||||
{
|
{
|
||||||
...summaryShape,
|
...summaryShape,
|
||||||
annotation: {
|
annotation: {
|
||||||
tags: [
|
tags: expect.arrayContaining([
|
||||||
expect.objectContaining({ name: 'tag1' }),
|
expect.objectContaining({ name: 'tag1' }),
|
||||||
expect.objectContaining({ name: 'tag2' }),
|
expect.objectContaining({ name: 'tag2' }),
|
||||||
],
|
]),
|
||||||
vote: 'up',
|
vote: 'up',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -691,10 +691,10 @@ describe('ExecutionService', () => {
|
||||||
{
|
{
|
||||||
...summaryShape,
|
...summaryShape,
|
||||||
annotation: {
|
annotation: {
|
||||||
tags: [
|
tags: expect.arrayContaining([
|
||||||
expect.objectContaining({ name: 'tag1' }),
|
expect.objectContaining({ name: 'tag1' }),
|
||||||
expect.objectContaining({ name: 'tag2' }),
|
expect.objectContaining({ name: 'tag2' }),
|
||||||
],
|
]),
|
||||||
vote: 'up',
|
vote: 'up',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue