From a7534292778a2133a6b6e67b52d2755c13a33da8 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Wed, 27 Oct 2021 19:38:45 +0100 Subject: [PATCH] Server: Fixed items.owner_id migration --- .../server/src/commands/MigrateCommand.ts | 7 +- .../migrations/20211027112530_item_owner.ts | 71 +++++++++++-------- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/packages/server/src/commands/MigrateCommand.ts b/packages/server/src/commands/MigrateCommand.ts index c12968a5054..b058ea87c5b 100644 --- a/packages/server/src/commands/MigrateCommand.ts +++ b/packages/server/src/commands/MigrateCommand.ts @@ -15,6 +15,7 @@ enum ArgvCommand { interface Argv { command: ArgvCommand; + disableTransactions?: boolean; } export default class MigrateCommand extends BaseCommand { @@ -53,13 +54,13 @@ export default class MigrateCommand extends BaseCommand { public async run(argv: Argv, runContext: RunContext): Promise { const commands: Record = { up: async () => { - await migrateUp(runContext.db); + await migrateUp(runContext.db, argv.disableTransactions); }, down: async () => { - await migrateDown(runContext.db); + await migrateDown(runContext.db, argv.disableTransactions); }, latest: async () => { - await migrateLatest(runContext.db); + await migrateLatest(runContext.db, argv.disableTransactions); }, list: async () => { const s = (await migrateList(runContext.db)) as string; diff --git a/packages/server/src/migrations/20211027112530_item_owner.ts b/packages/server/src/migrations/20211027112530_item_owner.ts index c023da782ec..16aedc70a79 100644 --- a/packages/server/src/migrations/20211027112530_item_owner.ts +++ b/packages/server/src/migrations/20211027112530_item_owner.ts @@ -1,41 +1,52 @@ import { Knex } from 'knex'; -import { DbConnection, isPostgres } from '../db'; +import { DbConnection } from '../db'; export async function up(db: DbConnection): Promise { - await db.schema.alterTable('items', (table: Knex.CreateTableBuilder) => { - table.string('owner_id', 32).defaultTo('').notNullable(); - }); + if (!(await db.schema.hasColumn('items', 'owner_id'))) { + await db.schema.alterTable('items', (table: Knex.CreateTableBuilder) => { + table.string('owner_id', 32).defaultTo('').notNullable(); + }); + } - if (isPostgres(db)) { - await db.raw(` - UPDATE items - SET owner_id = user_items.user_id - FROM user_items - WHERE user_items.item_id = items.id - `); - } else { - // Very inefficient way to set the owner_id but SQLite is probably not - // used with very large dataset. - - interface Row { - id: string; - user_id: string; - } + // This query never finishes - so can't use it + + // await db.raw(` + // UPDATE items^ + // SET owner_id = user_items.user_id + // FROM user_items + // WHERE user_items.item_id = items.id + // `); + + interface Row { + id: string; + user_id: string; + } + + const pageSize = 10000; + + const itemCount = (await db('items') + .count('id', { as: 'total' }) + .where('owner_id', '=', '') + .first())['total']; - while (true) { - const items: Row[] = await - db('items') - .join('user_items', 'items.id', 'user_items.item_id') - .select(['items.id', 'user_items.user_id']) - .where('owner_id', '=', '') - .limit(10000); + let itemDone = 0; - if (!items.length) break; + while (true) { + const items: Row[] = await db('items') + .join('user_items', 'items.id', 'user_items.item_id') + .select(['items.id', 'user_items.user_id']) + .where('owner_id', '=', '') + .limit(pageSize); - for (const item of items) { - await db('items').update({ owner_id: item.user_id }).where('id', '=', item.id); - } + if (!items.length) break; + + console.info(`Processing items ${itemDone} / ${itemCount}`); + + for (const item of items) { + await db('items').update({ owner_id: item.user_id }).where('id', '=', item.id); } + + itemDone += items.length; } await db.schema.alterTable('items', (table: Knex.CreateTableBuilder) => {