From 5caafed0f827914207ef0f17bf628015dafbde08 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 20 Oct 2021 20:01:49 +0100 Subject: [PATCH] Keep views up to date with table schema changes --- .../server/src/api/controllers/table/utils.js | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/packages/server/src/api/controllers/table/utils.js b/packages/server/src/api/controllers/table/utils.js index fd3ea6693c..9b5f11d865 100644 --- a/packages/server/src/api/controllers/table/utils.js +++ b/packages/server/src/api/controllers/table/utils.js @@ -13,6 +13,8 @@ const { isExternalTable, breakExternalTableId, } = require("../../../integrations/utils") +const { getViews, saveView } = require("../view/utils") +const viewTemplate = require("../view/viewBuilder") exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { let updatedRows = [] @@ -25,6 +27,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { } // check for renaming of columns or deleted columns if (rename || deletedColumns.length !== 0) { + // Update all rows const rows = await db.allDocs( getRowParams(updatedTable._id, null, { include_docs: true, @@ -39,6 +42,9 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { } return doc }) + + // Update views + await exports.checkForViewUpdates(db, updatedTable, rename, deletedColumns) delete updatedTable._rename } return { rows: updatedRows, table: updatedTable } @@ -237,4 +243,74 @@ exports.getTable = async (appId, tableId) => { } } +exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => { + const views = await getViews(db) + const tableViews = views.filter(view => view.meta.tableId === table._id) + + // Check each table view to see if impacted by this table action + for (let view of tableViews) { + let needsUpdated = false + + // First check for renames, otherwise check for deletions + if (rename) { + // Update calculation field if required + if (view.meta.field === rename.old) { + view.meta.field = rename.updated + needsUpdated = true + } + + // Update group by field if required + if (view.meta.groupBy === rename.old) { + view.meta.groupBy = rename.updated + needsUpdated = true + } + + // Update filters if required + view.meta.filters?.forEach(filter => { + if (filter.key === rename.old) { + filter.key = rename.updated + needsUpdated = true + } + }) + } else if (deletedColumns?.length) { + deletedColumns.forEach(column => { + // Remove calculation statement if required + if (view.meta.field === column) { + delete view.meta.field + delete view.meta.calculation + delete view.meta.groupBy + needsUpdated = true + } + + // Remove group by field if required + if (view.meta.groupBy === column) { + delete view.meta.groupBy + needsUpdated = true + } + + // Remove filters referencing deleted field if required + if (view.meta.filters?.length) { + const initialLength = view.meta.filters.length + view.meta.filters = view.meta.filters.filter(filter => { + return filter.key !== column + }) + if (initialLength !== view.meta.filters.length) { + needsUpdated = true + } + } + }) + } + + // Update view if required + if (needsUpdated) { + const newViewTemplate = viewTemplate(view.meta) + await saveView(db, null, view.name, newViewTemplate) + if (!newViewTemplate.meta.schema) { + newViewTemplate.meta.schema = table.schema + } + table.views[view.name] = newViewTemplate.meta + } + } +} + exports.TableSaveFunctions = TableSaveFunctions