diff --git a/backend/database/core.ts b/backend/database/core.ts index a68699f8..f02fe269 100644 --- a/backend/database/core.ts +++ b/backend/database/core.ts @@ -354,37 +354,25 @@ export default class DatabaseCore extends DatabaseBase { return (res?.count ?? 0) > 0; } - async #removeColumns(schemaName: string, targetColumns: string[]) { - const fields = this.schemaMap[schemaName]?.fields - .filter((f) => f.fieldtype !== FieldTypeEnum.Table && !f.computed) - .map((f) => f.fieldname); - const tableRows = await this.getAll(schemaName, { fields }); - this.prestigeTheTable(schemaName, tableRows); + async #dropColumns(schemaName: string, targetColumns: string[]) { + await this.knex!.schema.table(schemaName, (table) => { + table.dropColumns(...targetColumns); + }); } async prestigeTheTable(schemaName: string, tableRows: FieldValueMap[]) { - const max = 200; - // Alter table hacx for sqlite in case of schema change. const tempName = `__${schemaName}`; - await this.knex!.schema.dropTableIfExists(tempName); + // Create replacement table + await this.knex!.schema.dropTableIfExists(tempName); await this.knex!.raw('PRAGMA foreign_keys=OFF'); await this.#createTable(schemaName, tempName); - if (tableRows.length > 200) { - const fi = Math.floor(tableRows.length / max); - for (let i = 0; i <= fi; i++) { - const rowSlice = tableRows.slice(i * max, i + 1 * max); - if (rowSlice.length === 0) { - break; - } - await this.knex!.batchInsert(tempName, rowSlice); - } - } else { - await this.knex!.batchInsert(tempName, tableRows); - } + // Insert rows from source table into the replacement table + await this.knex!.batchInsert(tempName, tableRows, 200); + // Replace with the replacement table await this.knex!.schema.dropTable(schemaName); await this.knex!.schema.renameTable(tempName, schemaName); await this.knex!.raw('PRAGMA foreign_keys=ON'); @@ -593,21 +581,23 @@ export default class DatabaseCore extends DatabaseBase { const diff: ColumnDiff = await this.#getColumnDiff(schemaName); const newForeignKeys: Field[] = await this.#getNewForeignKeys(schemaName); - return this.knex!.schema.table(schemaName, (table) => { - if (diff.added.length) { - for (const field of diff.added) { - this.#buildColumnForTable(table, field); - } + await this.knex!.schema.table(schemaName, (table) => { + if (!diff.added.length) { + return; } - if (diff.removed.length) { - this.#removeColumns(schemaName, diff.removed); - } - }).then(() => { - if (newForeignKeys.length) { - return this.#addForeignKeys(schemaName, newForeignKeys); + for (const field of diff.added) { + this.#buildColumnForTable(table, field); } }); + + if (diff.removed.length) { + await this.#dropColumns(schemaName, diff.removed); + } + + if (newForeignKeys.length) { + await this.#addForeignKeys(schemaName, newForeignKeys); + } } async #createTable(schemaName: string, tableName?: string) { @@ -687,34 +677,8 @@ export default class DatabaseCore extends DatabaseBase { } async #addForeignKeys(schemaName: string, newForeignKeys: Field[]) { - await this.knex!.raw('PRAGMA foreign_keys=OFF'); - await this.knex!.raw('BEGIN TRANSACTION'); - - const tempName = 'TEMP' + schemaName; - - // create temp table - await this.#createTable(schemaName, tempName); - - try { - // copy from old to new table - await this.knex!(tempName).insert(this.knex!.select().from(schemaName)); - } catch (err) { - await this.knex!.raw('ROLLBACK'); - await this.knex!.raw('PRAGMA foreign_keys=ON'); - - const rows = await this.knex!.select().from(schemaName); - await this.prestigeTheTable(schemaName, rows); - return; - } - - // drop old table - await this.knex!.schema.dropTable(schemaName); - - // rename new table - await this.knex!.schema.renameTable(tempName, schemaName); - - await this.knex!.raw('COMMIT'); - await this.knex!.raw('PRAGMA foreign_keys=ON'); + const tableRows = await this.knex!.select().from(schemaName); + await this.prestigeTheTable(schemaName, tableRows); } async #loadChildren(