From 81cbbc0cd521487fbd25f25471c818f06f4ab83c Mon Sep 17 00:00:00 2001 From: Daria Date: Mon, 11 Aug 2025 17:44:34 +0300 Subject: [PATCH] feat(core): Add a migration for data stores (no-changelog) (#18045) --- .../1754475614601-CreateDataStoreTables.ts | 46 +++++++++++++++++++ packages/@n8n/db/src/migrations/dsl/table.ts | 13 +++++- .../@n8n/db/src/migrations/mysqldb/index.ts | 2 + .../db/src/migrations/postgresdb/index.ts | 2 + .../@n8n/db/src/migrations/sqlite/index.ts | 2 + 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 packages/@n8n/db/src/migrations/common/1754475614601-CreateDataStoreTables.ts diff --git a/packages/@n8n/db/src/migrations/common/1754475614601-CreateDataStoreTables.ts b/packages/@n8n/db/src/migrations/common/1754475614601-CreateDataStoreTables.ts new file mode 100644 index 0000000000..7e8372b59d --- /dev/null +++ b/packages/@n8n/db/src/migrations/common/1754475614601-CreateDataStoreTables.ts @@ -0,0 +1,46 @@ +import type { MigrationContext, ReversibleMigration } from '../migration-types'; + +const DATA_STORE_TABLE_NAME = 'data_store'; +const DATA_STORE_COLUMN_TABLE_NAME = 'data_store_column'; + +export class CreateDataStoreTables1754475614601 implements ReversibleMigration { + async up({ schemaBuilder: { createTable, column } }: MigrationContext) { + await createTable(DATA_STORE_TABLE_NAME) + .withColumns( + column('id').varchar(36).primary, + column('name').varchar(128).notNull, + column('projectId').varchar(36).notNull, + column('sizeBytes').int.default(0).notNull, + ) + .withForeignKey('projectId', { + tableName: 'project', + columnName: 'id', + onDelete: 'CASCADE', + }) + .withUniqueConstraintOn(['projectId', 'name']).withTimestamps; + + await createTable(DATA_STORE_COLUMN_TABLE_NAME) + .withColumns( + column('id').varchar(36).primary.notNull, + column('name').varchar(128).notNull, + column('type') + .varchar(32) + .notNull.comment( + 'Expected: string, number, boolean, or date (not enforced as a constraint)', + ), + column('index').int.notNull.comment('Column order, starting from 0 (0 = first column)'), + column('dataStoreId').varchar(36).notNull, + ) + .withForeignKey('dataStoreId', { + tableName: DATA_STORE_TABLE_NAME, + columnName: 'id', + onDelete: 'CASCADE', + }) + .withUniqueConstraintOn(['dataStoreId', 'name']).withTimestamps; + } + + async down({ schemaBuilder: { dropTable } }: MigrationContext) { + await dropTable(DATA_STORE_COLUMN_TABLE_NAME); + await dropTable(DATA_STORE_TABLE_NAME); + } +} diff --git a/packages/@n8n/db/src/migrations/dsl/table.ts b/packages/@n8n/db/src/migrations/dsl/table.ts index 76df89a33c..faa2c51ab2 100644 --- a/packages/@n8n/db/src/migrations/dsl/table.ts +++ b/packages/@n8n/db/src/migrations/dsl/table.ts @@ -1,5 +1,5 @@ import type { TableForeignKeyOptions, TableIndexOptions, QueryRunner } from '@n8n/typeorm'; -import { Table, TableColumn, TableForeignKey } from '@n8n/typeorm'; +import { Table, TableColumn, TableForeignKey, TableUnique } from '@n8n/typeorm'; import { UnexpectedError } from 'n8n-workflow'; import LazyPromise from 'p-lazy'; @@ -24,6 +24,8 @@ export class CreateTable extends TableOperation { private indices = new Set(); + private uniqueConstraints = new Set(); + private foreignKeys = new Set(); withColumns(...columns: Column[]) { @@ -45,6 +47,12 @@ export class CreateTable extends TableOperation { return this; } + withUniqueConstraintOn(columnName: string | string[]) { + const columnNames = Array.isArray(columnName) ? columnName : [columnName]; + this.uniqueConstraints.add(new TableUnique({ columnNames })); + return this; + } + withForeignKey( columnName: string, ref: { @@ -69,12 +77,13 @@ export class CreateTable extends TableOperation { async execute(queryRunner: QueryRunner) { const { driver } = queryRunner.connection; - const { columns, tableName: name, prefix, indices, foreignKeys } = this; + const { columns, tableName: name, prefix, indices, uniqueConstraints, foreignKeys } = this; return await queryRunner.createTable( new Table({ name: `${prefix}${name}`, columns: columns.map((c) => c.toOptions(driver)), ...(indices.size ? { indices: [...indices] } : {}), + ...(uniqueConstraints.size ? { uniques: [...uniqueConstraints] } : {}), ...(foreignKeys.size ? { foreignKeys: [...foreignKeys] } : {}), ...('mysql' in driver ? { engine: 'InnoDB' } : {}), }), diff --git a/packages/@n8n/db/src/migrations/mysqldb/index.ts b/packages/@n8n/db/src/migrations/mysqldb/index.ts index 2410768770..4cd64ed081 100644 --- a/packages/@n8n/db/src/migrations/mysqldb/index.ts +++ b/packages/@n8n/db/src/migrations/mysqldb/index.ts @@ -89,6 +89,7 @@ import { DropRoleTable1745934666077 } from '../common/1745934666077-DropRoleTabl import { AddProjectDescriptionColumn1747824239000 } from '../common/1747824239000-AddProjectDescriptionColumn'; import { AddLastActiveAtColumnToUser1750252139166 } from '../common/1750252139166-AddLastActiveAtColumnToUser'; import { AddInputsOutputsToTestCaseExecution1752669793000 } from '../common/1752669793000-AddInputsOutputsToTestCaseExecution'; +import { CreateDataStoreTables1754475614601 } from '../common/1754475614601-CreateDataStoreTables'; import type { Migration } from '../migration-types'; import { UpdateParentFolderIdColumn1740445074052 } from '../mysqldb/1740445074052-UpdateParentFolderIdColumn'; @@ -185,4 +186,5 @@ export const mysqlMigrations: Migration[] = [ AddProjectDescriptionColumn1747824239000, AddLastActiveAtColumnToUser1750252139166, AddInputsOutputsToTestCaseExecution1752669793000, + CreateDataStoreTables1754475614601, ]; diff --git a/packages/@n8n/db/src/migrations/postgresdb/index.ts b/packages/@n8n/db/src/migrations/postgresdb/index.ts index 1096d89ff5..7ee90699ae 100644 --- a/packages/@n8n/db/src/migrations/postgresdb/index.ts +++ b/packages/@n8n/db/src/migrations/postgresdb/index.ts @@ -89,6 +89,7 @@ import { AddWorkflowArchivedColumn1745934666076 } from '../common/1745934666076- import { DropRoleTable1745934666077 } from '../common/1745934666077-DropRoleTable'; import { AddProjectDescriptionColumn1747824239000 } from '../common/1747824239000-AddProjectDescriptionColumn'; import { AddLastActiveAtColumnToUser1750252139166 } from '../common/1750252139166-AddLastActiveAtColumnToUser'; +import { CreateDataStoreTables1754475614601 } from '../common/1754475614601-CreateDataStoreTables'; import type { Migration } from '../migration-types'; export const postgresMigrations: Migration[] = [ @@ -183,4 +184,5 @@ export const postgresMigrations: Migration[] = [ AddProjectDescriptionColumn1747824239000, AddLastActiveAtColumnToUser1750252139166, AddInputsOutputsToTestCaseExecution1752669793000, + CreateDataStoreTables1754475614601, ]; diff --git a/packages/@n8n/db/src/migrations/sqlite/index.ts b/packages/@n8n/db/src/migrations/sqlite/index.ts index d3768e7cf3..c3d80ff661 100644 --- a/packages/@n8n/db/src/migrations/sqlite/index.ts +++ b/packages/@n8n/db/src/migrations/sqlite/index.ts @@ -86,6 +86,7 @@ import { DropRoleTable1745934666077 } from '../common/1745934666077-DropRoleTabl import { AddProjectDescriptionColumn1747824239000 } from '../common/1747824239000-AddProjectDescriptionColumn'; import { AddLastActiveAtColumnToUser1750252139166 } from '../common/1750252139166-AddLastActiveAtColumnToUser'; import { AddInputsOutputsToTestCaseExecution1752669793000 } from '../common/1752669793000-AddInputsOutputsToTestCaseExecution'; +import { CreateDataStoreTables1754475614601 } from '../common/1754475614601-CreateDataStoreTables'; import type { Migration } from '../migration-types'; const sqliteMigrations: Migration[] = [ @@ -177,6 +178,7 @@ const sqliteMigrations: Migration[] = [ AddProjectDescriptionColumn1747824239000, AddLastActiveAtColumnToUser1750252139166, AddInputsOutputsToTestCaseExecution1752669793000, + CreateDataStoreTables1754475614601, ]; export { sqliteMigrations };