diff --git a/app/utils/db.ts b/app/utils/db.ts index 581bd546..408dc967 100644 --- a/app/utils/db.ts +++ b/app/utils/db.ts @@ -73,3 +73,30 @@ export async function normalizeOrderField(table: string): Promise { ); }); } + +/** + * Normalizes contributor order separately for every milestone. + * + * A contributor may have multiple roles in a milestone, so all of its pivot + * rows must receive the same order value. + */ +export async function normalizeContributorOrder(): Promise { + await db.rawQuery(` + WITH normalized AS ( + SELECT + "milestone_id", + "contributor_id", + ROW_NUMBER() OVER ( + PARTITION BY "milestone_id" + ORDER BY MIN("order") ASC, "contributor_id" ASC + ) AS "new_order" + FROM "contributor_roles" + GROUP BY "milestone_id", "contributor_id" + ) + UPDATE "contributor_roles" AS "target" + SET "order" = "normalized"."new_order" + FROM "normalized" + WHERE "target"."milestone_id" = "normalized"."milestone_id" + AND "target"."contributor_id" = "normalized"."contributor_id"; + `); +} diff --git a/commands/db_normalize_order.ts b/commands/db_normalize_order.ts index 1b55839c..b817aa26 100644 --- a/commands/db_normalize_order.ts +++ b/commands/db_normalize_order.ts @@ -1,13 +1,13 @@ import { BaseCommand, flags } from "@adonisjs/core/ace"; import type { CommandOptions } from "@adonisjs/core/types/ace"; -import { normalizeOrderField } from "#utils/db"; +import { normalizeContributorOrder, normalizeOrderField } from "#utils/db"; export default class DbNormalizeOrder extends BaseCommand { static commandName = "db:normalize-order"; static description = "Replaces the order columns with a fresh integer sequence, keeping the entry order unchanged"; - private orderedTables = ["contributors", "guide_articles", "guide_questions"]; + private orderedTables = ["guide_articles", "guide_questions"]; static options: CommandOptions = { startApp: true, @@ -34,6 +34,10 @@ export default class DbNormalizeOrder extends BaseCommand { } const tasks = this.ui.tasks(); + tasks.add("Normalize contributor order for each milestone", async () => { + await normalizeContributorOrder(); + return "done"; + }); for (const table of this.orderedTables) { tasks.add(`Normalize order for table "${table}"`, async () => { await normalizeOrderField(table);