From 9adc4cc801b0ffa3fa6c5220d73291ee93335814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 10:16:59 +0200 Subject: [PATCH 01/17] refactor: Disallow orphan executions --- .../1693554410387-DisallowOrphanExecutions.ts | 26 +++++++ .../src/databases/migrations/mysqldb/index.ts | 2 + .../1693554410387-DisallowOrphanExecutions.ts | 28 +++++++ .../databases/migrations/postgresdb/index.ts | 2 + .../1693554410387-DisallowOrphanExecutions.ts | 77 +++++++++++++++++++ .../src/databases/migrations/sqlite/index.ts | 2 + 6 files changed, 137 insertions(+) create mode 100644 packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts create mode 100644 packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts create mode 100644 packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..0e04dba8da8cd --- /dev/null +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,26 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + /** + * Ensure all executions point to a workflow. + */ + async up({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query( + `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, + ); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); + } +} diff --git a/packages/cli/src/databases/migrations/mysqldb/index.ts b/packages/cli/src/databases/migrations/mysqldb/index.ts index ce89cb312cb18..fb20d00e8a55b 100644 --- a/packages/cli/src/databases/migrations/mysqldb/index.ts +++ b/packages/cli/src/databases/migrations/mysqldb/index.ts @@ -46,6 +46,7 @@ import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; export const mysqlMigrations: Migration[] = [ InitialMigration1588157391238, @@ -95,4 +96,5 @@ export const mysqlMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; diff --git a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..c03318bf0712b --- /dev/null +++ b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,28 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + /** + * Ensure all executions point to a workflow. + */ + async up({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query( + `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} SET NOT NULL;`, + ); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query( + `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} DROP NOT NULL;`, + ); + } +} diff --git a/packages/cli/src/databases/migrations/postgresdb/index.ts b/packages/cli/src/databases/migrations/postgresdb/index.ts index 89249058e6633..eb19bf1795d85 100644 --- a/packages/cli/src/databases/migrations/postgresdb/index.ts +++ b/packages/cli/src/databases/migrations/postgresdb/index.ts @@ -44,6 +44,7 @@ import { AddMissingPrimaryKeyOnExecutionData1690787606731 } from './169078760673 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; export const postgresMigrations: Migration[] = [ InitialMigration1587669153312, @@ -91,4 +92,5 @@ export const postgresMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..0be36a154400f --- /dev/null +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,77 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + transaction = false as const; + + /** + * Ensure all executions point to a workflow. Recreate table because sqlite + * does not support modifying column. + */ + async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + + await createTable('temp') + .withColumns( + column('id').int.primary.autoGenerate.notNull, + column('workflowId').varchar(36).notNull, // only change + column('finished').bool.notNull, + column('mode').varchar().notNull, + column('retryOf').varchar(), + column('retrySuccessId').varchar(), + column('startedAt').timestamp().notNull, + column('stoppedAt').timestamp(), + column('waitTill').timestamp(), + column('status').varchar(), + ) + .withForeignKey('workflowId', { + tableName: 'workflow_entity', + columnName: 'id', + onDelete: 'CASCADE', + }); + + await runQuery( + `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, + ); + + await runQuery(`DROP TABLE ${executionEntity};`); + + await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + + await createTable('temp') + .withColumns( + column('id').int.primary.autoGenerate.notNull, + column('workflowId').varchar(36), // only change + column('finished').bool.notNull, + column('mode').varchar().notNull, + column('retryOf').varchar(), + column('retrySuccessId').varchar(), + column('startedAt').timestamp().notNull, + column('stoppedAt').timestamp(), + column('waitTill').timestamp(), + column('status').varchar(), + ) + .withForeignKey('workflowId', { + tableName: 'workflow_entity', + columnName: 'id', + onDelete: 'CASCADE', + }); + + await runQuery( + `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, + ); + + await runQuery(`DROP TABLE ${executionEntity};`); + + await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + } +} diff --git a/packages/cli/src/databases/migrations/sqlite/index.ts b/packages/cli/src/databases/migrations/sqlite/index.ts index 9bac59767b0e3..2411f7d6127a3 100644 --- a/packages/cli/src/databases/migrations/sqlite/index.ts +++ b/packages/cli/src/databases/migrations/sqlite/index.ts @@ -43,6 +43,7 @@ import { RemoveResetPasswordColumns1690000000030 } from './1690000000030-RemoveR import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; const sqliteMigrations: Migration[] = [ InitialMigration1588102412422, @@ -89,6 +90,7 @@ const sqliteMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; export { sqliteMigrations }; From a377768d5e57b6025a8a635058041ea1cbc7e44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 11:33:33 +0200 Subject: [PATCH 02/17] Add backticks for MySQL --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0e04dba8da8cd..0b15f106cfa4d 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -8,9 +8,9 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query(`DELETE FROM \`${executionEntity}\` WHERE \`${workflowId}\` IS NULL;`); await queryRunner.query( - `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, + `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36) NOT NULL;`, ); } @@ -21,6 +21,8 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); + await queryRunner.query( + `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36);`, + ); } } From 022bee29c4c76782bd559749f3c70b24401fac6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 11:50:56 +0200 Subject: [PATCH 03/17] Revert "Add backticks for MySQL" This reverts commit a377768d5e57b6025a8a635058041ea1cbc7e44b. --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0b15f106cfa4d..0e04dba8da8cd 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -8,9 +8,9 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`DELETE FROM \`${executionEntity}\` WHERE \`${workflowId}\` IS NULL;`); + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( - `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36) NOT NULL;`, + `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, ); } @@ -21,8 +21,6 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query( - `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36);`, - ); + await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); } } From b41180cd83c6b03e5fe9831c297f3d56074a905c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 12:14:05 +0200 Subject: [PATCH 04/17] Fix silly mistake --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 4 ++-- .../postgresdb/1693554410387-DisallowOrphanExecutions.ts | 4 ++-- .../sqlite/1693554410387-DisallowOrphanExecutions.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0e04dba8da8cd..651962463950a 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -6,7 +6,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( @@ -19,7 +19,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async down({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); } diff --git a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts index c03318bf0712b..41df87026b006 100644 --- a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts @@ -6,7 +6,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( @@ -19,7 +19,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async down({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query( `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} DROP NOT NULL;`, diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 0be36a154400f..334d01102c0a4 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -9,7 +9,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); From 672d2d77d3ddb0f498a54bac6acd6b28df052c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 16:57:10 +0200 Subject: [PATCH 05/17] Add indices --- .../1693554410387-DisallowOrphanExecutions.ts | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 334d01102c0a4..20bc89c051e70 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -7,7 +7,11 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio * Ensure all executions point to a workflow. Recreate table because sqlite * does not support modifying column. */ - async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + async up({ + escape, + schemaBuilder: { createTable, column, createIndex, dropIndex }, + runQuery, + }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.columnName('workflowId'); @@ -32,6 +36,29 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio onDelete: 'CASCADE', }); + const isUnique = false; + + await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); + await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); + await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await dropIndex( + 'execution_entity', + ['status', 'workflowId'], + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); + + await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); + await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); + await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await createIndex( + 'temp', + ['status', 'workflowId'], + isUnique, + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); + await runQuery( `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, ); @@ -44,7 +71,11 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio /** * Reversal excludes restoring deleted rows. */ - async down({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + async down({ + escape, + schemaBuilder: { createTable, column, createIndex, dropIndex }, + runQuery, + }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); await createTable('temp') @@ -66,6 +97,29 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio onDelete: 'CASCADE', }); + await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); + await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); + await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await dropIndex( + 'execution_entity', + ['status', 'workflowId'], + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); + + const isUnique = false; + + await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); + await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); + await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await createIndex( + 'temp', + ['status', 'workflowId'], + isUnique, + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); + await runQuery( `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, ); From af7d7d21f421b5efe11d9d710ed7f0395f447a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 4 Sep 2023 12:46:13 +0200 Subject: [PATCH 06/17] feat(core): Add new DSL for adding and dropping `NOT NULL` constraints (no-changelog) --- packages/cli/src/databases/dsl/Table.ts | 48 ++++++++++++++++++++++--- packages/cli/src/databases/dsl/index.ts | 7 +++- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/databases/dsl/Table.ts b/packages/cli/src/databases/dsl/Table.ts index b2735cadc9a61..79e02d75c1240 100644 --- a/packages/cli/src/databases/dsl/Table.ts +++ b/packages/cli/src/databases/dsl/Table.ts @@ -6,11 +6,7 @@ import { Column } from './Column'; abstract class TableOperation extends LazyPromise { abstract execute(queryRunner: QueryRunner): Promise; - constructor( - protected tableName: string, - protected prefix: string, - queryRunner: QueryRunner, - ) { + constructor(protected tableName: string, protected prefix: string, queryRunner: QueryRunner) { super((resolve) => { void this.execute(queryRunner).then(resolve); }); @@ -116,3 +112,45 @@ export class DropColumns extends TableOperation { return queryRunner.dropColumns(`${prefix}${tableName}`, columnNames); } } + +export class AddNotNull extends TableOperation { + constructor( + tableName: string, + protected columnName: string, + prefix: string, + queryRunner: QueryRunner, + ) { + super(tableName, prefix, queryRunner); + } + + async execute(queryRunner: QueryRunner) { + const { tableName, prefix, columnName } = this; + const table = await queryRunner.getTable(`${prefix}${tableName}`); + if (!table) throw new Error(`No table found with the name ${tableName}`); + const oldColumn = table.findColumnByName(columnName)!; + const newColumn = oldColumn.clone(); + newColumn.isNullable = false; + return queryRunner.changeColumn(table, oldColumn, newColumn); + } +} + +export class DropNotNull extends TableOperation { + constructor( + tableName: string, + protected columnName: string, + prefix: string, + queryRunner: QueryRunner, + ) { + super(tableName, prefix, queryRunner); + } + + async execute(queryRunner: QueryRunner) { + const { tableName, prefix, columnName } = this; + const table = await queryRunner.getTable(`${prefix}${tableName}`); + if (!table) throw new Error(`No table found with the name ${tableName}`); + const oldColumn = table.findColumnByName(columnName)!; + const newColumn = oldColumn.clone(); + newColumn.isNullable = true; + return queryRunner.changeColumn(table, oldColumn, newColumn); + } +} diff --git a/packages/cli/src/databases/dsl/index.ts b/packages/cli/src/databases/dsl/index.ts index bd5a06a5910ee..1e85c31a4b05a 100644 --- a/packages/cli/src/databases/dsl/index.ts +++ b/packages/cli/src/databases/dsl/index.ts @@ -1,6 +1,6 @@ import type { QueryRunner } from 'typeorm'; import { Column } from './Column'; -import { AddColumns, CreateTable, DropColumns, DropTable } from './Table'; +import { AddColumns, AddNotNull, CreateTable, DropColumns, DropNotNull, DropTable } from './Table'; import { CreateIndex, DropIndex } from './Indices'; export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunner) => ({ @@ -26,5 +26,10 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne dropIndex: (tableName: string, columnNames: string[], customIndexName?: string) => new DropIndex(tablePrefix, tableName, columnNames, queryRunner, customIndexName), + addNotNull: (tableName: string, columnName: string) => + new AddNotNull(tablePrefix, tableName, columnName, queryRunner), + dropNotNull: (tableName: string, columnName: string) => + new DropNotNull(tablePrefix, tableName, columnName, queryRunner), + /* eslint-enable */ }); From 50fb9ea3f0aceb9ba18c331e64ba830946a51923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 4 Sep 2023 12:46:13 +0200 Subject: [PATCH 07/17] feat(core): Add new DSL for adding and dropping `NOT NULL` constraints (no-changelog) --- packages/cli/src/databases/dsl/Table.ts | 50 ++++++++++++++++++++++--- packages/cli/src/databases/dsl/index.ts | 7 +++- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/databases/dsl/Table.ts b/packages/cli/src/databases/dsl/Table.ts index b2735cadc9a61..5e7a55b37c796 100644 --- a/packages/cli/src/databases/dsl/Table.ts +++ b/packages/cli/src/databases/dsl/Table.ts @@ -6,11 +6,7 @@ import { Column } from './Column'; abstract class TableOperation extends LazyPromise { abstract execute(queryRunner: QueryRunner): Promise; - constructor( - protected tableName: string, - protected prefix: string, - queryRunner: QueryRunner, - ) { + constructor(protected tableName: string, protected prefix: string, queryRunner: QueryRunner) { super((resolve) => { void this.execute(queryRunner).then(resolve); }); @@ -116,3 +112,47 @@ export class DropColumns extends TableOperation { return queryRunner.dropColumns(`${prefix}${tableName}`, columnNames); } } + +class ModifyNotNull extends TableOperation { + constructor( + tableName: string, + protected columnName: string, + protected isNullable: boolean, + prefix: string, + queryRunner: QueryRunner, + ) { + super(tableName, prefix, queryRunner); + } + + async execute(queryRunner: QueryRunner) { + const { tableName, prefix, columnName, isNullable } = this; + const table = await queryRunner.getTable(`${prefix}${tableName}`); + if (!table) throw new Error(`No table found with the name ${tableName}`); + const oldColumn = table.findColumnByName(columnName)!; + const newColumn = oldColumn.clone(); + newColumn.isNullable = isNullable; + return queryRunner.changeColumn(table, oldColumn, newColumn); + } +} + +export class AddNotNull extends ModifyNotNull { + constructor( + tableName: string, + protected columnName: string, + prefix: string, + queryRunner: QueryRunner, + ) { + super(tableName, columnName, false, prefix, queryRunner); + } +} + +export class DropNotNull extends ModifyNotNull { + constructor( + tableName: string, + protected columnName: string, + prefix: string, + queryRunner: QueryRunner, + ) { + super(tableName, columnName, true, prefix, queryRunner); + } +} diff --git a/packages/cli/src/databases/dsl/index.ts b/packages/cli/src/databases/dsl/index.ts index bd5a06a5910ee..1e85c31a4b05a 100644 --- a/packages/cli/src/databases/dsl/index.ts +++ b/packages/cli/src/databases/dsl/index.ts @@ -1,6 +1,6 @@ import type { QueryRunner } from 'typeorm'; import { Column } from './Column'; -import { AddColumns, CreateTable, DropColumns, DropTable } from './Table'; +import { AddColumns, AddNotNull, CreateTable, DropColumns, DropNotNull, DropTable } from './Table'; import { CreateIndex, DropIndex } from './Indices'; export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunner) => ({ @@ -26,5 +26,10 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne dropIndex: (tableName: string, columnNames: string[], customIndexName?: string) => new DropIndex(tablePrefix, tableName, columnNames, queryRunner, customIndexName), + addNotNull: (tableName: string, columnName: string) => + new AddNotNull(tablePrefix, tableName, columnName, queryRunner), + dropNotNull: (tableName: string, columnName: string) => + new DropNotNull(tablePrefix, tableName, columnName, queryRunner), + /* eslint-enable */ }); From 7cc3edd964fe826804721c564ea16c80b68a65e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 10:16:59 +0200 Subject: [PATCH 08/17] refactor: Disallow orphan executions --- .../1693554410387-DisallowOrphanExecutions.ts | 26 +++++++ .../src/databases/migrations/mysqldb/index.ts | 2 + .../1693554410387-DisallowOrphanExecutions.ts | 28 +++++++ .../databases/migrations/postgresdb/index.ts | 2 + .../1693554410387-DisallowOrphanExecutions.ts | 77 +++++++++++++++++++ .../src/databases/migrations/sqlite/index.ts | 2 + 6 files changed, 137 insertions(+) create mode 100644 packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts create mode 100644 packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts create mode 100644 packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..0e04dba8da8cd --- /dev/null +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,26 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + /** + * Ensure all executions point to a workflow. + */ + async up({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query( + `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, + ); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); + } +} diff --git a/packages/cli/src/databases/migrations/mysqldb/index.ts b/packages/cli/src/databases/migrations/mysqldb/index.ts index ce89cb312cb18..fb20d00e8a55b 100644 --- a/packages/cli/src/databases/migrations/mysqldb/index.ts +++ b/packages/cli/src/databases/migrations/mysqldb/index.ts @@ -46,6 +46,7 @@ import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; export const mysqlMigrations: Migration[] = [ InitialMigration1588157391238, @@ -95,4 +96,5 @@ export const mysqlMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; diff --git a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..c03318bf0712b --- /dev/null +++ b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,28 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + /** + * Ensure all executions point to a workflow. + */ + async up({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query( + `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} SET NOT NULL;`, + ); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ queryRunner, escape }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await queryRunner.query( + `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} DROP NOT NULL;`, + ); + } +} diff --git a/packages/cli/src/databases/migrations/postgresdb/index.ts b/packages/cli/src/databases/migrations/postgresdb/index.ts index 89249058e6633..eb19bf1795d85 100644 --- a/packages/cli/src/databases/migrations/postgresdb/index.ts +++ b/packages/cli/src/databases/migrations/postgresdb/index.ts @@ -44,6 +44,7 @@ import { AddMissingPrimaryKeyOnExecutionData1690787606731 } from './169078760673 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; export const postgresMigrations: Migration[] = [ InitialMigration1587669153312, @@ -91,4 +92,5 @@ export const postgresMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts new file mode 100644 index 0000000000000..0be36a154400f --- /dev/null +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -0,0 +1,77 @@ +import type { MigrationContext, ReversibleMigration } from '@db/types'; + +export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { + transaction = false as const; + + /** + * Ensure all executions point to a workflow. Recreate table because sqlite + * does not support modifying column. + */ + async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + const workflowId = escape.tableName('workflowId'); + + await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + + await createTable('temp') + .withColumns( + column('id').int.primary.autoGenerate.notNull, + column('workflowId').varchar(36).notNull, // only change + column('finished').bool.notNull, + column('mode').varchar().notNull, + column('retryOf').varchar(), + column('retrySuccessId').varchar(), + column('startedAt').timestamp().notNull, + column('stoppedAt').timestamp(), + column('waitTill').timestamp(), + column('status').varchar(), + ) + .withForeignKey('workflowId', { + tableName: 'workflow_entity', + columnName: 'id', + onDelete: 'CASCADE', + }); + + await runQuery( + `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, + ); + + await runQuery(`DROP TABLE ${executionEntity};`); + + await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + } + + /** + * Reversal excludes restoring deleted rows. + */ + async down({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + const executionEntity = escape.tableName('execution_entity'); + + await createTable('temp') + .withColumns( + column('id').int.primary.autoGenerate.notNull, + column('workflowId').varchar(36), // only change + column('finished').bool.notNull, + column('mode').varchar().notNull, + column('retryOf').varchar(), + column('retrySuccessId').varchar(), + column('startedAt').timestamp().notNull, + column('stoppedAt').timestamp(), + column('waitTill').timestamp(), + column('status').varchar(), + ) + .withForeignKey('workflowId', { + tableName: 'workflow_entity', + columnName: 'id', + onDelete: 'CASCADE', + }); + + await runQuery( + `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, + ); + + await runQuery(`DROP TABLE ${executionEntity};`); + + await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + } +} diff --git a/packages/cli/src/databases/migrations/sqlite/index.ts b/packages/cli/src/databases/migrations/sqlite/index.ts index 9bac59767b0e3..2411f7d6127a3 100644 --- a/packages/cli/src/databases/migrations/sqlite/index.ts +++ b/packages/cli/src/databases/migrations/sqlite/index.ts @@ -43,6 +43,7 @@ import { RemoveResetPasswordColumns1690000000030 } from './1690000000030-RemoveR import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; +import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; const sqliteMigrations: Migration[] = [ InitialMigration1588102412422, @@ -89,6 +90,7 @@ const sqliteMigrations: Migration[] = [ CreateWorkflowNameIndex1691088862123, AddMfaColumns1690000000030, CreateWorkflowHistoryTable1692967111175, + DisallowOrphanExecutions1693554410387, ]; export { sqliteMigrations }; From 716464542bfe66bb01a8a9f4af5ae658b3f6bb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 11:33:33 +0200 Subject: [PATCH 09/17] Add backticks for MySQL --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0e04dba8da8cd..0b15f106cfa4d 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -8,9 +8,9 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); + await queryRunner.query(`DELETE FROM \`${executionEntity}\` WHERE \`${workflowId}\` IS NULL;`); await queryRunner.query( - `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, + `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36) NOT NULL;`, ); } @@ -21,6 +21,8 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); + await queryRunner.query( + `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36);`, + ); } } From a797bcf4578d0f3bb7e11d350140f42003f2c267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 11:50:56 +0200 Subject: [PATCH 10/17] Revert "Add backticks for MySQL" This reverts commit a377768d5e57b6025a8a635058041ea1cbc7e44b. --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0b15f106cfa4d..0e04dba8da8cd 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -8,9 +8,9 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query(`DELETE FROM \`${executionEntity}\` WHERE \`${workflowId}\` IS NULL;`); + await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( - `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36) NOT NULL;`, + `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, ); } @@ -21,8 +21,6 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.tableName('workflowId'); - await queryRunner.query( - `ALTER TABLE \`${executionEntity}\` MODIFY \`${workflowId}\` VARCHAR(36);`, - ); + await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); } } From 9052696b1b28bbc4847ee1139ba10d800d7e3cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 12:14:05 +0200 Subject: [PATCH 11/17] Fix silly mistake --- .../mysqldb/1693554410387-DisallowOrphanExecutions.ts | 4 ++-- .../postgresdb/1693554410387-DisallowOrphanExecutions.ts | 4 ++-- .../sqlite/1693554410387-DisallowOrphanExecutions.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts index 0e04dba8da8cd..651962463950a 100644 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts @@ -6,7 +6,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( @@ -19,7 +19,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async down({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); } diff --git a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts index c03318bf0712b..41df87026b006 100644 --- a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts @@ -6,7 +6,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); await queryRunner.query( @@ -19,7 +19,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async down({ queryRunner, escape }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await queryRunner.query( `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} DROP NOT NULL;`, diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 0be36a154400f..334d01102c0a4 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -9,7 +9,7 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio */ async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.tableName('workflowId'); + const workflowId = escape.columnName('workflowId'); await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); From 5db211195561e0a47b27714ca7627df0cb806a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Fri, 1 Sep 2023 16:57:10 +0200 Subject: [PATCH 12/17] Add indices --- .../1693554410387-DisallowOrphanExecutions.ts | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 334d01102c0a4..20bc89c051e70 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -7,7 +7,11 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio * Ensure all executions point to a workflow. Recreate table because sqlite * does not support modifying column. */ - async up({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + async up({ + escape, + schemaBuilder: { createTable, column, createIndex, dropIndex }, + runQuery, + }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.columnName('workflowId'); @@ -32,6 +36,29 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio onDelete: 'CASCADE', }); + const isUnique = false; + + await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); + await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); + await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await dropIndex( + 'execution_entity', + ['status', 'workflowId'], + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); + + await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); + await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); + await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await createIndex( + 'temp', + ['status', 'workflowId'], + isUnique, + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); + await runQuery( `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, ); @@ -44,7 +71,11 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio /** * Reversal excludes restoring deleted rows. */ - async down({ escape, schemaBuilder: { createTable, column }, runQuery }: MigrationContext) { + async down({ + escape, + schemaBuilder: { createTable, column, createIndex, dropIndex }, + runQuery, + }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); await createTable('temp') @@ -66,6 +97,29 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio onDelete: 'CASCADE', }); + await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); + await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); + await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await dropIndex( + 'execution_entity', + ['status', 'workflowId'], + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); + + const isUnique = false; + + await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); + await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); + await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); + await createIndex( + 'temp', + ['status', 'workflowId'], + isUnique, + 'IDX_8b6f3f9ae234f137d707b98f3bf43584', + ); + await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); + await runQuery( `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, ); From a07ecd5c5cdadadcf7de07c0e34aba88478ab689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Mon, 4 Sep 2023 12:57:58 +0200 Subject: [PATCH 13/17] Simplify using DSL updates --- packages/cli/src/databases/dsl/Table.ts | 10 +- .../1693554410387-DisallowOrphanExecutions.ts | 117 +----------------- 2 files changed, 12 insertions(+), 115 deletions(-) diff --git a/packages/cli/src/databases/dsl/Table.ts b/packages/cli/src/databases/dsl/Table.ts index 79e02d75c1240..79d4a462c4cbd 100644 --- a/packages/cli/src/databases/dsl/Table.ts +++ b/packages/cli/src/databases/dsl/Table.ts @@ -6,7 +6,11 @@ import { Column } from './Column'; abstract class TableOperation extends LazyPromise { abstract execute(queryRunner: QueryRunner): Promise; - constructor(protected tableName: string, protected prefix: string, queryRunner: QueryRunner) { + constructor( + protected tableName: string, + protected prefix: string, + queryRunner: QueryRunner, + ) { super((resolve) => { void this.execute(queryRunner).then(resolve); }); @@ -115,9 +119,9 @@ export class DropColumns extends TableOperation { export class AddNotNull extends TableOperation { constructor( + prefix: string, tableName: string, protected columnName: string, - prefix: string, queryRunner: QueryRunner, ) { super(tableName, prefix, queryRunner); @@ -136,9 +140,9 @@ export class AddNotNull extends TableOperation { export class DropNotNull extends TableOperation { constructor( + prefix: string, tableName: string, protected columnName: string, - prefix: string, queryRunner: QueryRunner, ) { super(tableName, prefix, queryRunner); diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 20bc89c051e70..f18425d52efe1 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -4,128 +4,21 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio transaction = false as const; /** - * Ensure all executions point to a workflow. Recreate table because sqlite - * does not support modifying column. + * Ensure all executions point to a workflow. */ - async up({ - escape, - schemaBuilder: { createTable, column, createIndex, dropIndex }, - runQuery, - }: MigrationContext) { + async up({ escape, schemaBuilder: { addNotNull }, runQuery }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.columnName('workflowId'); await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); - await createTable('temp') - .withColumns( - column('id').int.primary.autoGenerate.notNull, - column('workflowId').varchar(36).notNull, // only change - column('finished').bool.notNull, - column('mode').varchar().notNull, - column('retryOf').varchar(), - column('retrySuccessId').varchar(), - column('startedAt').timestamp().notNull, - column('stoppedAt').timestamp(), - column('waitTill').timestamp(), - column('status').varchar(), - ) - .withForeignKey('workflowId', { - tableName: 'workflow_entity', - columnName: 'id', - onDelete: 'CASCADE', - }); - - const isUnique = false; - - await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); - await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); - await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await dropIndex( - 'execution_entity', - ['status', 'workflowId'], - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); - - await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); - await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); - await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await createIndex( - 'temp', - ['status', 'workflowId'], - isUnique, - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); - - await runQuery( - `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, - ); - - await runQuery(`DROP TABLE ${executionEntity};`); - - await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + await addNotNull('execution_entity', 'workflowId'); } /** * Reversal excludes restoring deleted rows. */ - async down({ - escape, - schemaBuilder: { createTable, column, createIndex, dropIndex }, - runQuery, - }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - - await createTable('temp') - .withColumns( - column('id').int.primary.autoGenerate.notNull, - column('workflowId').varchar(36), // only change - column('finished').bool.notNull, - column('mode').varchar().notNull, - column('retryOf').varchar(), - column('retrySuccessId').varchar(), - column('startedAt').timestamp().notNull, - column('stoppedAt').timestamp(), - column('waitTill').timestamp(), - column('status').varchar(), - ) - .withForeignKey('workflowId', { - tableName: 'workflow_entity', - columnName: 'id', - onDelete: 'CASCADE', - }); - - await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); - await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); - await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await dropIndex( - 'execution_entity', - ['status', 'workflowId'], - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); - - const isUnique = false; - - await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); - await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); - await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await createIndex( - 'temp', - ['status', 'workflowId'], - isUnique, - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); - - await runQuery( - `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, - ); - - await runQuery(`DROP TABLE ${executionEntity};`); - - await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + async down({ schemaBuilder: { dropNotNull } }: MigrationContext) { + await dropNotNull('execution_entity', 'workflowId'); } } From 573538824fa379c0fc2a06dcc3501a977dd4fe72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 4 Sep 2023 13:01:57 +0200 Subject: [PATCH 14/17] use consistent order of fields in DSL methods --- packages/cli/src/databases/dsl/Indices.ts | 6 +++--- packages/cli/src/databases/dsl/index.ts | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/databases/dsl/Indices.ts b/packages/cli/src/databases/dsl/Indices.ts index d6b868e2aa71b..d07c6db558e1c 100644 --- a/packages/cli/src/databases/dsl/Indices.ts +++ b/packages/cli/src/databases/dsl/Indices.ts @@ -13,9 +13,9 @@ abstract class IndexOperation extends LazyPromise { } constructor( - protected tablePrefix: string, protected tableName: string, protected columnNames: string[], + protected tablePrefix: string, queryRunner: QueryRunner, protected customIndexName?: string, ) { @@ -27,14 +27,14 @@ abstract class IndexOperation extends LazyPromise { export class CreateIndex extends IndexOperation { constructor( - tablePrefix: string, tableName: string, columnNames: string[], protected isUnique: boolean, + tablePrefix: string, queryRunner: QueryRunner, customIndexName?: string, ) { - super(tablePrefix, tableName, columnNames, queryRunner, customIndexName); + super(tableName, columnNames, tablePrefix, queryRunner, customIndexName); } async execute(queryRunner: QueryRunner) { diff --git a/packages/cli/src/databases/dsl/index.ts b/packages/cli/src/databases/dsl/index.ts index 1e85c31a4b05a..6eb6df8bc97b5 100644 --- a/packages/cli/src/databases/dsl/index.ts +++ b/packages/cli/src/databases/dsl/index.ts @@ -21,15 +21,15 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne columnNames: string[], isUnique = false, customIndexName?: string, - ) => new CreateIndex(tablePrefix, tableName, columnNames, isUnique, queryRunner, customIndexName), + ) => new CreateIndex(tableName, columnNames, isUnique, tablePrefix, queryRunner, customIndexName), dropIndex: (tableName: string, columnNames: string[], customIndexName?: string) => - new DropIndex(tablePrefix, tableName, columnNames, queryRunner, customIndexName), + new DropIndex(tableName, columnNames, tablePrefix, queryRunner, customIndexName), addNotNull: (tableName: string, columnName: string) => - new AddNotNull(tablePrefix, tableName, columnName, queryRunner), + new AddNotNull(tableName, columnName, tablePrefix, queryRunner), dropNotNull: (tableName: string, columnName: string) => - new DropNotNull(tablePrefix, tableName, columnName, queryRunner), + new DropNotNull(tableName, columnName, tablePrefix, queryRunner), /* eslint-enable */ }); From a7eca82ab19026e7c28d09b5cce8b8bbbc7cd23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 4 Sep 2023 13:02:17 +0200 Subject: [PATCH 15/17] DSL exceptions should reject the lazy promise --- packages/cli/src/databases/dsl/Table.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/databases/dsl/Table.ts b/packages/cli/src/databases/dsl/Table.ts index 5e7a55b37c796..a93caeca92138 100644 --- a/packages/cli/src/databases/dsl/Table.ts +++ b/packages/cli/src/databases/dsl/Table.ts @@ -7,8 +7,8 @@ abstract class TableOperation extends LazyPromise { abstract execute(queryRunner: QueryRunner): Promise; constructor(protected tableName: string, protected prefix: string, queryRunner: QueryRunner) { - super((resolve) => { - void this.execute(queryRunner).then(resolve); + super((resolve, reject) => { + void this.execute(queryRunner).then(resolve).catch(reject); }); } } From ed5ca4b949b4a2f62399b39548f2dd5bb3b8ae25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 4 Sep 2023 13:02:34 +0200 Subject: [PATCH 16/17] Update 1693554410387-DisallowOrphanExecutions.ts --- .../1693554410387-DisallowOrphanExecutions.ts | 114 +----------------- 1 file changed, 4 insertions(+), 110 deletions(-) diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts index 20bc89c051e70..88f67ebd6aa15 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts @@ -7,125 +7,19 @@ export class DisallowOrphanExecutions1693554410387 implements ReversibleMigratio * Ensure all executions point to a workflow. Recreate table because sqlite * does not support modifying column. */ - async up({ - escape, - schemaBuilder: { createTable, column, createIndex, dropIndex }, - runQuery, - }: MigrationContext) { + async up({ escape, schemaBuilder: { dropNotNull }, runQuery }: MigrationContext) { const executionEntity = escape.tableName('execution_entity'); const workflowId = escape.columnName('workflowId'); await runQuery(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); - await createTable('temp') - .withColumns( - column('id').int.primary.autoGenerate.notNull, - column('workflowId').varchar(36).notNull, // only change - column('finished').bool.notNull, - column('mode').varchar().notNull, - column('retryOf').varchar(), - column('retrySuccessId').varchar(), - column('startedAt').timestamp().notNull, - column('stoppedAt').timestamp(), - column('waitTill').timestamp(), - column('status').varchar(), - ) - .withForeignKey('workflowId', { - tableName: 'workflow_entity', - columnName: 'id', - onDelete: 'CASCADE', - }); - - const isUnique = false; - - await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); - await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); - await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await dropIndex( - 'execution_entity', - ['status', 'workflowId'], - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); - - await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); - await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); - await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await createIndex( - 'temp', - ['status', 'workflowId'], - isUnique, - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); - - await runQuery( - `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, - ); - - await runQuery(`DROP TABLE ${executionEntity};`); - - await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + await dropNotNull('execution_entity', 'workflowId'); } /** * Reversal excludes restoring deleted rows. */ - async down({ - escape, - schemaBuilder: { createTable, column, createIndex, dropIndex }, - runQuery, - }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - - await createTable('temp') - .withColumns( - column('id').int.primary.autoGenerate.notNull, - column('workflowId').varchar(36), // only change - column('finished').bool.notNull, - column('mode').varchar().notNull, - column('retryOf').varchar(), - column('retrySuccessId').varchar(), - column('startedAt').timestamp().notNull, - column('stoppedAt').timestamp(), - column('waitTill').timestamp(), - column('status').varchar(), - ) - .withForeignKey('workflowId', { - tableName: 'workflow_entity', - columnName: 'id', - onDelete: 'CASCADE', - }); - - await dropIndex('execution_entity', ['waitTill'], 'idx_execution_entity_wait_till'); - await dropIndex('execution_entity', ['stoppedAt'], 'idx_execution_entity_stopped_at'); - await dropIndex('execution_entity', ['waitTill', 'id'], 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await dropIndex( - 'execution_entity', - ['status', 'workflowId'], - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await dropIndex('execution_entity', ['workflowId', 'id'], 'IDX_81fc04c8a17de15835713505e4'); - - const isUnique = false; - - await createIndex('temp', ['waitTill'], isUnique, 'idx_execution_entity_wait_till'); - await createIndex('temp', ['stoppedAt'], isUnique, 'idx_execution_entity_stopped_at'); - await createIndex('temp', ['waitTill', 'id'], isUnique, 'IDX_b94b45ce2c73ce46c54f20b5f9'); - await createIndex( - 'temp', - ['status', 'workflowId'], - isUnique, - 'IDX_8b6f3f9ae234f137d707b98f3bf43584', - ); - await createIndex('temp', ['workflowId', 'id'], isUnique, 'IDX_81fc04c8a17de15835713505e4'); - - await runQuery( - `INSERT INTO "temp" ("id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status") SELECT "id", "workflowId", "finished", "mode", "retryOf", "retrySuccessId", "startedAt", "stoppedAt", "waitTill", "status" FROM ${executionEntity};`, - ); - - await runQuery(`DROP TABLE ${executionEntity};`); - - await runQuery(`ALTER TABLE "temp" RENAME TO ${executionEntity};`); + async down({ schemaBuilder: { addNotNull } }: MigrationContext) { + await addNotNull('execution_entity', 'workflowId'); } } From d21401b3dbc986bb94f6cf65041fe00872911a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Mon, 4 Sep 2023 14:01:14 +0200 Subject: [PATCH 17/17] Cleanup --- packages/cli/src/databases/dsl/index.ts | 5 ---- .../1693554410387-DisallowOrphanExecutions.ts | 2 -- .../1693554410387-DisallowOrphanExecutions.ts | 26 ----------------- .../src/databases/migrations/mysqldb/index.ts | 2 +- .../1693554410387-DisallowOrphanExecutions.ts | 28 ------------------- .../databases/migrations/postgresdb/index.ts | 2 +- .../src/databases/migrations/sqlite/index.ts | 2 +- 7 files changed, 3 insertions(+), 64 deletions(-) rename packages/cli/src/databases/migrations/{sqlite => common}/1693554410387-DisallowOrphanExecutions.ts (95%) delete mode 100644 packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts delete mode 100644 packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts diff --git a/packages/cli/src/databases/dsl/index.ts b/packages/cli/src/databases/dsl/index.ts index 69a3c5aef5bd4..6eb6df8bc97b5 100644 --- a/packages/cli/src/databases/dsl/index.ts +++ b/packages/cli/src/databases/dsl/index.ts @@ -31,10 +31,5 @@ export const createSchemaBuilder = (tablePrefix: string, queryRunner: QueryRunne dropNotNull: (tableName: string, columnName: string) => new DropNotNull(tableName, columnName, tablePrefix, queryRunner), - addNotNull: (tableName: string, columnName: string) => - new AddNotNull(tablePrefix, tableName, columnName, queryRunner), - dropNotNull: (tableName: string, columnName: string) => - new DropNotNull(tablePrefix, tableName, columnName, queryRunner), - /* eslint-enable */ }); diff --git a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/common/1693554410387-DisallowOrphanExecutions.ts similarity index 95% rename from packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts rename to packages/cli/src/databases/migrations/common/1693554410387-DisallowOrphanExecutions.ts index f18425d52efe1..c0f74ec0bb2f2 100644 --- a/packages/cli/src/databases/migrations/sqlite/1693554410387-DisallowOrphanExecutions.ts +++ b/packages/cli/src/databases/migrations/common/1693554410387-DisallowOrphanExecutions.ts @@ -1,8 +1,6 @@ import type { MigrationContext, ReversibleMigration } from '@db/types'; export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { - transaction = false as const; - /** * Ensure all executions point to a workflow. */ diff --git a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts deleted file mode 100644 index 651962463950a..0000000000000 --- a/packages/cli/src/databases/migrations/mysqldb/1693554410387-DisallowOrphanExecutions.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { MigrationContext, ReversibleMigration } from '@db/types'; - -export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { - /** - * Ensure all executions point to a workflow. - */ - async up({ queryRunner, escape }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.columnName('workflowId'); - - await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); - await queryRunner.query( - `ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36) NOT NULL;`, - ); - } - - /** - * Reversal excludes restoring deleted rows. - */ - async down({ queryRunner, escape }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.columnName('workflowId'); - - await queryRunner.query(`ALTER TABLE ${executionEntity} MODIFY ${workflowId} VARCHAR(36);`); - } -} diff --git a/packages/cli/src/databases/migrations/mysqldb/index.ts b/packages/cli/src/databases/migrations/mysqldb/index.ts index fb20d00e8a55b..6fc762ddf28b1 100644 --- a/packages/cli/src/databases/migrations/mysqldb/index.ts +++ b/packages/cli/src/databases/migrations/mysqldb/index.ts @@ -46,7 +46,7 @@ import { RemoveResetPasswordColumns1690000000030 } from '../common/1690000000030 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; -import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; +import { DisallowOrphanExecutions1693554410387 } from '../common/1693554410387-DisallowOrphanExecutions'; export const mysqlMigrations: Migration[] = [ InitialMigration1588157391238, diff --git a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts b/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts deleted file mode 100644 index 41df87026b006..0000000000000 --- a/packages/cli/src/databases/migrations/postgresdb/1693554410387-DisallowOrphanExecutions.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { MigrationContext, ReversibleMigration } from '@db/types'; - -export class DisallowOrphanExecutions1693554410387 implements ReversibleMigration { - /** - * Ensure all executions point to a workflow. - */ - async up({ queryRunner, escape }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.columnName('workflowId'); - - await queryRunner.query(`DELETE FROM ${executionEntity} WHERE ${workflowId} IS NULL;`); - await queryRunner.query( - `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} SET NOT NULL;`, - ); - } - - /** - * Reversal excludes restoring deleted rows. - */ - async down({ queryRunner, escape }: MigrationContext) { - const executionEntity = escape.tableName('execution_entity'); - const workflowId = escape.columnName('workflowId'); - - await queryRunner.query( - `ALTER TABLE ${executionEntity} ALTER COLUMN ${workflowId} DROP NOT NULL;`, - ); - } -} diff --git a/packages/cli/src/databases/migrations/postgresdb/index.ts b/packages/cli/src/databases/migrations/postgresdb/index.ts index eb19bf1795d85..6a39cfb18f52c 100644 --- a/packages/cli/src/databases/migrations/postgresdb/index.ts +++ b/packages/cli/src/databases/migrations/postgresdb/index.ts @@ -44,7 +44,7 @@ import { AddMissingPrimaryKeyOnExecutionData1690787606731 } from './169078760673 import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './../common/1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; -import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; +import { DisallowOrphanExecutions1693554410387 } from '../common/1693554410387-DisallowOrphanExecutions'; export const postgresMigrations: Migration[] = [ InitialMigration1587669153312, diff --git a/packages/cli/src/databases/migrations/sqlite/index.ts b/packages/cli/src/databases/migrations/sqlite/index.ts index 2411f7d6127a3..b10c0edfa404b 100644 --- a/packages/cli/src/databases/migrations/sqlite/index.ts +++ b/packages/cli/src/databases/migrations/sqlite/index.ts @@ -43,7 +43,7 @@ import { RemoveResetPasswordColumns1690000000030 } from './1690000000030-RemoveR import { CreateWorkflowNameIndex1691088862123 } from '../common/1691088862123-CreateWorkflowNameIndex'; import { AddMfaColumns1690000000030 } from './1690000000040-AddMfaColumns'; import { CreateWorkflowHistoryTable1692967111175 } from '../common/1692967111175-CreateWorkflowHistoryTable'; -import { DisallowOrphanExecutions1693554410387 } from './1693554410387-DisallowOrphanExecutions'; +import { DisallowOrphanExecutions1693554410387 } from '../common/1693554410387-DisallowOrphanExecutions'; const sqliteMigrations: Migration[] = [ InitialMigration1588102412422,