diff --git a/packages/client/src/api/queries.js b/packages/client/src/api/queries.js index 8db41ecf5c..8735d9587b 100644 --- a/packages/client/src/api/queries.js +++ b/packages/client/src/api/queries.js @@ -20,7 +20,7 @@ export const executeQuery = async ({ queryId, parameters }) => { notificationStore.actions.error("An error has occurred") } else if (!query.readable) { notificationStore.actions.success("Query executed successfully") - dataSourceStore.actions.invalidateDataSource(query.datasourceId) + await dataSourceStore.actions.invalidateDataSource(query.datasourceId) } return res } diff --git a/packages/client/src/api/rows.js b/packages/client/src/api/rows.js index 6e1ac31279..acd083454d 100644 --- a/packages/client/src/api/rows.js +++ b/packages/client/src/api/rows.js @@ -31,7 +31,7 @@ export const saveRow = async row => { : notificationStore.actions.success("Row saved") // Refresh related datasources - dataSourceStore.actions.invalidateDataSource(row.tableId) + await dataSourceStore.actions.invalidateDataSource(row.tableId) return res } @@ -52,7 +52,7 @@ export const updateRow = async row => { : notificationStore.actions.success("Row updated") // Refresh related datasources - dataSourceStore.actions.invalidateDataSource(row.tableId) + await dataSourceStore.actions.invalidateDataSource(row.tableId) return res } @@ -76,7 +76,7 @@ export const deleteRow = async ({ tableId, rowId, revId }) => { : notificationStore.actions.success("Row deleted") // Refresh related datasources - dataSourceStore.actions.invalidateDataSource(tableId) + await dataSourceStore.actions.invalidateDataSource(tableId) return res } @@ -99,7 +99,7 @@ export const deleteRows = async ({ tableId, rows }) => { : notificationStore.actions.success(`${rows.length} row(s) deleted`) // Refresh related datasources - dataSourceStore.actions.invalidateDataSource(tableId) + await dataSourceStore.actions.invalidateDataSource(tableId) return res } diff --git a/packages/client/src/stores/dataSource.js b/packages/client/src/stores/dataSource.js index 963548158d..256571018d 100644 --- a/packages/client/src/stores/dataSource.js +++ b/packages/client/src/stores/dataSource.js @@ -1,4 +1,5 @@ import { writable, get } from "svelte/store" +import { fetchTableDefinition } from "../api" export const createDataSourceStore = () => { const store = writable([]) @@ -9,43 +10,32 @@ export const createDataSourceStore = () => { return } - // Create a list of all relevant dataSource IDs which would require that - // this dataSource is refreshed - let dataSourceIds = [] + // Extract the relevant datasource ID for this datasource + let dataSourceId = null // Extract table ID if (dataSource.type === "table" || dataSource.type === "view") { - if (dataSource.tableId) { - dataSourceIds.push(dataSource.tableId) - } + dataSourceId = dataSource.tableId } - // Extract both table IDs from both sides of the relationship + // Only one side of the relationship is required as a trigger, as it will + // automatically invalidate related table IDs else if (dataSource.type === "link") { - if (dataSource.rowTableId) { - dataSourceIds.push(dataSource.rowTableId) - } - if (dataSource.tableId) { - dataSourceIds.push(dataSource.tableId) - } + dataSourceId = dataSource.tableId || dataSource.rowTableId } // Extract the dataSource ID (not the query ID) for queries else if (dataSource.type === "query") { - if (dataSource.dataSourceId) { - dataSourceIds.push(dataSource.dataSourceId) - } + dataSourceId = dataSource.dataSourceId } // Store configs for each relevant dataSource ID - if (dataSourceIds.length) { + if (dataSourceId) { store.update(state => { - dataSourceIds.forEach(id => { - state.push({ - dataSourceId: id, - instanceId, - refresh, - }) + state.push({ + dataSourceId, + instanceId, + refresh, }) return state }) @@ -62,13 +52,10 @@ export const createDataSourceStore = () => { // Invalidates a specific dataSource ID by refreshing all instances // which depend on data from that dataSource - const invalidateDataSource = dataSourceId => { - const relatedInstances = get(store).filter(instance => { - return instance.dataSourceId === dataSourceId - }) - relatedInstances?.forEach(instance => { - instance.refresh() - }) + const invalidateDataSource = async dataSourceId => { + if (!dataSourceId) { + return + } // Emit this as a window event, so parent screens which are iframing us in // can also invalidate the same datasource @@ -77,6 +64,32 @@ export const createDataSourceStore = () => { detail: { dataSourceId }, }) ) + + let invalidations = [dataSourceId] + + // Fetch related table IDs from table schema + const definition = await fetchTableDefinition(dataSourceId) + const schema = definition?.schema + if (schema) { + Object.values(schema).forEach(fieldSchema => { + if (fieldSchema.type === "link" && fieldSchema.tableId) { + invalidations.push(fieldSchema.tableId) + } + }) + } + + // Remove and dupes + invalidations = [...new Set(invalidations)] + + // Invalidate all sources + invalidations.forEach(id => { + const relatedInstances = get(store).filter(instance => { + return instance.dataSourceId === id + }) + relatedInstances?.forEach(instance => { + instance.refresh() + }) + }) } return {