refactor(core): Set up binary data table (#22137)

This commit is contained in:
Iván Ovejero
2025-11-21 13:44:48 +01:00
committed by GitHub
parent 3857f6fd44
commit d509dad475
6 changed files with 82 additions and 3 deletions
@@ -0,0 +1,26 @@
import type { MigrationContext, ReversibleMigration } from '../migration-types';
const tableName = 'binary_data';
export class CreateBinaryDataTable1763716655000 implements ReversibleMigration {
async up({ schemaBuilder: { createTable, column } }: MigrationContext) {
await createTable(tableName)
.withColumns(
column('fileId').uuid.primary.notNull,
column('sourceType')
.varchar(50)
.notNull.comment("Source the file belongs to, e.g. 'execution'"),
column('sourceId').varchar(255).notNull.comment('ID of the source, e.g. execution ID'),
column('data').binary.notNull.comment('Raw, not base64 encoded'),
column('mimeType').varchar(255),
column('fileName').varchar(255),
column('fileSize').int.notNull.comment('In bytes'),
)
.withEnumCheck('sourceType', ['execution', 'chat_message_attachment'])
.withIndexOn(['sourceType', 'sourceId']).withTimestamps;
}
async down({ schemaBuilder: { dropTable } }: MigrationContext) {
await dropTable(tableName);
}
}
+15 -1
View File
@@ -12,7 +12,8 @@ export class Column {
| 'uuid'
| 'double'
| 'bigint'
| 'smallint';
| 'smallint'
| 'binary';
private isGenerated = false;
@@ -99,6 +100,11 @@ export class Column {
return this;
}
get binary() {
this.type = 'binary';
return this;
}
get primary() {
this.isPrimary = true;
return this;
@@ -190,6 +196,14 @@ export class Column {
}
} else if (type === 'bigint') {
options.type = 'bigint';
} else if (type === 'binary') {
if (isPostgres) {
options.type = 'bytea';
} else if (isMysql) {
options.type = 'longblob';
} else if (isSqlite) {
options.type = 'blob';
}
}
if (
+35 -2
View File
@@ -1,5 +1,5 @@
import type { TableForeignKeyOptions, TableIndexOptions, QueryRunner } from '@n8n/typeorm';
import { Table, TableColumn, TableForeignKey, TableUnique } from '@n8n/typeorm';
import { Table, TableCheck, TableColumn, TableForeignKey, TableUnique } from '@n8n/typeorm';
import { UnexpectedError } from 'n8n-workflow';
import LazyPromise from 'p-lazy';
@@ -28,6 +28,10 @@ export class CreateTable extends TableOperation {
private foreignKeys = new Set<TableForeignKeyOptions>();
private checks = new Set<TableCheck>();
private enumChecks: Array<{ columnName: string; values: string[] }> = [];
withColumns(...columns: Column[]) {
this.columns.push(...columns);
return this;
@@ -58,6 +62,16 @@ export class CreateTable extends TableOperation {
return this;
}
withCheck(name: string, expression: string) {
this.checks.add(new TableCheck({ name, expression }));
return this;
}
withEnumCheck(columnName: string, values: string[]) {
this.enumChecks.push({ columnName, values });
return this;
}
withForeignKey(
columnName: string,
ref: {
@@ -82,7 +96,25 @@ export class CreateTable extends TableOperation {
async execute(queryRunner: QueryRunner) {
const { driver } = queryRunner.connection;
const { columns, tableName: name, prefix, indices, uniqueConstraints, foreignKeys } = this;
const {
columns,
tableName: name,
prefix,
indices,
uniqueConstraints,
foreignKeys,
checks,
enumChecks,
} = this;
for (const { columnName, values } of enumChecks) {
const checkName = `CHK_${prefix}${name}_${columnName}`;
const escapedColumnName = driver.escape(columnName);
const escapedValues = values.map((v) => `'${v.replace(/'/g, "''")}'`).join(', ');
const expression = `${escapedColumnName} IN (${escapedValues})`;
checks.add(new TableCheck({ name: checkName, expression }));
}
return await queryRunner.createTable(
new Table({
name: `${prefix}${name}`,
@@ -90,6 +122,7 @@ export class CreateTable extends TableOperation {
...(indices.size ? { indices: [...indices] } : {}),
...(uniqueConstraints.size ? { uniques: [...uniqueConstraints] } : {}),
...(foreignKeys.size ? { foreignKeys: [...foreignKeys] } : {}),
...(checks.size ? { checks: [...checks] } : {}),
...('mysql' in driver ? { engine: 'InnoDB' } : {}),
}),
true,
@@ -117,6 +117,7 @@ import { AddIsGlobalColumnToCredentialsTable1762771954619 } from '../common/1762
import { AddWorkflowHistoryAutoSaveFields1762847206508 } from '../common/1762847206508-AddWorkflowHistoryAutoSaveFields';
import { AddActiveVersionIdColumn1763047800000 } from '../common/1763047800000-AddActiveVersionIdColumn';
import { ChangeOAuthStateColumnToUnboundedVarchar1763572724000 } from '../common/1763572724000-ChangeOAuthStateColumnToUnboundedVarchar';
import { CreateBinaryDataTable1763716655000 } from '../common/1763716655000-CreateBinaryDataTable';
import type { Migration } from '../migration-types';
export const mysqlMigrations: Migration[] = [
@@ -239,4 +240,5 @@ export const mysqlMigrations: Migration[] = [
ChangeOAuthStateColumnToUnboundedVarchar1763572724000,
AddAttachmentsToChatHubMessages1761773155024,
AddActiveVersionIdColumn1763047800000,
CreateBinaryDataTable1763716655000,
];
@@ -117,6 +117,7 @@ import { AddIsGlobalColumnToCredentialsTable1762771954619 } from '../common/1762
import { AddWorkflowHistoryAutoSaveFields1762847206508 } from '../common/1762847206508-AddWorkflowHistoryAutoSaveFields';
import { AddActiveVersionIdColumn1763047800000 } from '../common/1763047800000-AddActiveVersionIdColumn';
import { ChangeOAuthStateColumnToUnboundedVarchar1763572724000 } from '../common/1763572724000-ChangeOAuthStateColumnToUnboundedVarchar';
import { CreateBinaryDataTable1763716655000 } from '../common/1763716655000-CreateBinaryDataTable';
import type { Migration } from '../migration-types';
export const postgresMigrations: Migration[] = [
@@ -239,4 +240,5 @@ export const postgresMigrations: Migration[] = [
ChangeOAuthStateColumnToUnboundedVarchar1763572724000,
AddAttachmentsToChatHubMessages1761773155024,
AddActiveVersionIdColumn1763047800000,
CreateBinaryDataTable1763716655000,
];
@@ -113,6 +113,7 @@ import { AddIsGlobalColumnToCredentialsTable1762771954619 } from '../common/1762
import { AddWorkflowHistoryAutoSaveFields1762847206508 } from '../common/1762847206508-AddWorkflowHistoryAutoSaveFields';
import { AddActiveVersionIdColumn1763047800000 } from '../common/1763047800000-AddActiveVersionIdColumn';
import { ChangeOAuthStateColumnToUnboundedVarchar1763572724000 } from '../common/1763572724000-ChangeOAuthStateColumnToUnboundedVarchar';
import { CreateBinaryDataTable1763716655000 } from '../common/1763716655000-CreateBinaryDataTable';
import type { Migration } from '../migration-types';
const sqliteMigrations: Migration[] = [
@@ -231,6 +232,7 @@ const sqliteMigrations: Migration[] = [
ChangeOAuthStateColumnToUnboundedVarchar1763572724000,
AddAttachmentsToChatHubMessages1761773155024,
AddActiveVersionIdColumn1763047800000,
CreateBinaryDataTable1763716655000,
];
export { sqliteMigrations };