From 8681e4d4e9f8385544b4ed83c28af5a09db7bd24 Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Mon, 13 Apr 2026 21:50:00 -0600 Subject: [PATCH 1/2] fix: Load data button not working for high cost query tables (#44812) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Reset the table rows query after the user confirms loading data on a high-cost table, so React Query re-executes the fetch without the preflight check - Close the confirmation dialog after the user clicks "I understand, proceed" **Root cause:** `preflightCheck` is intentionally excluded from the React Query query key (to avoid duplicate cache entries). When the user clicked "Load data", the preflight flag flipped to `false` but the query key stayed the same — so React Query returned the cached error instead of refetching. ## Test plan - [x] Navigate to a table with high estimated query cost (triggers "Data not loaded to protect database performance") - [x] Click "Load data" → "I understand, proceed" - [x] Verify the dialog closes and table data loads - [x] Verify the warning does not reappear for the same table in the same session To test this you can run this locally with COST_THRESHOLD set to a low value (< 10) Fixes FE-2979 ## Summary by CodeRabbit * **Bug Fixes** * Confirming the high-cost warning now closes the dialog and proceeds with loading as expected. * Improved query cache key composition so queries reflect the full set of relevant parameters for correct caching. * Loading from the grid error now properly clears related cached results and proceeds when the user confirms. --- .../grid/components/grid/GridError.tsx | 19 ++++++++++++++++--- apps/studio/components/ui/HighQueryCost.tsx | 8 +++++--- .../data/table-rows/table-rows-query.ts | 7 ++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/studio/components/grid/components/grid/GridError.tsx b/apps/studio/components/grid/components/grid/GridError.tsx index b7654a52d1d..b3870798673 100644 --- a/apps/studio/components/grid/components/grid/GridError.tsx +++ b/apps/studio/components/grid/components/grid/GridError.tsx @@ -1,3 +1,4 @@ +import { useQueryClient } from '@tanstack/react-query' import { useParams } from 'common' import { useCallback } from 'react' import { Button } from 'ui' @@ -13,6 +14,7 @@ import { HighCostError } from '@/components/ui/HighQueryCost' import { InlineLink } from '@/components/ui/InlineLink' import { ENTITY_TYPE } from '@/data/entity-types/entity-type-constants' import { COST_THRESHOLD_ERROR } from '@/data/sql/execute-sql-query' +import { tableRowKeys } from '@/data/table-rows/keys' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { useTableEditorStateSnapshot } from '@/state/table-editor' import { useTableEditorTableStateSnapshot } from '@/state/table-editor-table' @@ -22,6 +24,8 @@ export const GridError = ({ error }: { error?: ResponseError | null }) => { const { id: _id } = useParams() const tableId = _id ? Number(_id) : undefined + const queryClient = useQueryClient() + const { data: project } = useSelectedProjectQuery() const newFilterBarEnabled = useIsTableFilterBarEnabled() const { filters: oldFilters, clearFilters: clearOldFilters } = useTableFilter() const { filters: newFilters, clearFilters: clearNewFilters } = useTableFilterNew() @@ -38,6 +42,17 @@ export const GridError = ({ error }: { error?: ResponseError | null }) => { } }, [clearOldFilters, clearNewFilters, newFilterBarEnabled]) + const handleLoadData = useCallback(() => { + if (!!tableId) { + tableEditorSnap.setTableToIgnorePreflightCheck(tableId) + + // Remove the cached error so useQuery re-fetches on the next render. + queryClient.removeQueries({ + queryKey: tableRowKeys.tableRowsAndCount(project?.ref, tableId), + }) + } + }, [tableEditorSnap, tableId, queryClient, project?.ref]) + if (!error) return null const tableEntityType = snap.originalTable?.entity_type @@ -63,9 +78,7 @@ export const GridError = ({ error }: { error?: ResponseError | null }) => { 'Remove any sorts or filters on unindexed columns, or', 'Create indexes for columns that you want to filter or sort on', ]} - onSelectLoadData={() => { - if (!!tableId) tableEditorSnap.setTableToIgnorePreflightCheck(tableId) - }} + onSelectLoadData={handleLoadData} /> ) } else if (isForeignTableMissingVaultKeyError) { diff --git a/apps/studio/components/ui/HighQueryCost.tsx b/apps/studio/components/ui/HighQueryCost.tsx index ca266201e1c..ce092d20f4c 100644 --- a/apps/studio/components/ui/HighQueryCost.tsx +++ b/apps/studio/components/ui/HighQueryCost.tsx @@ -171,9 +171,11 @@ const LoadDataWarningDialog = ({ Cancel - + + + diff --git a/apps/studio/data/table-rows/table-rows-query.ts b/apps/studio/data/table-rows/table-rows-query.ts index 524479225ed..57341288317 100644 --- a/apps/studio/data/table-rows/table-rows-query.ts +++ b/apps/studio/data/table-rows/table-rows-query.ts @@ -394,14 +394,15 @@ export const useTableRowsQuery = ( const queryClient = useQueryClient() const { connectionString, identifier: readReplicaIdentifier } = useConnectionStringForReadOps() - // [Joshen] Exclude preflightCheck from query key - const { preflightCheck, ...othersArgs } = args + // [Ali] Exclude preflightCheck from query key — it controls how the query + // executes (whether an EXPLAIN guard runs first), not what data is returned. + const { preflightCheck, ...queryKeyArgs } = args return useQuery({ queryKey: tableRowKeys.tableRows(projectRef, { table: { id: tableId }, readReplicaIdentifier, - ...othersArgs, + ...queryKeyArgs, }), queryFn: ({ signal }) => getTableRows({ queryClient, projectRef, connectionString, tableId, ...args }, signal), From f1a48f8c50e50b99b0b962c6698716909cc9b6f9 Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Tue, 14 Apr 2026 13:06:08 +0900 Subject: [PATCH 2/2] chore(studio): skip Sentry source map upload for local builds (#44837) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only wrap with `withSentryConfig` when running on Vercel (`VERCEL === '1'`), matching the existing pattern used for HSTS headers on line 510. The Sentry webpack plugin's `runAfterProductionCompile` step adds ~24s to local production builds for source map upload that isn't needed outside of deployments. **Changed:** - Gate `withSentryConfig` on `process.env.VERCEL === '1'` in addition to `NEXT_PUBLIC_IS_PLATFORM === 'true'` ## To test - Run `pnpm build:studio` locally with `NEXT_PUBLIC_IS_PLATFORM=true` – confirm no `runAfterProductionCompile` step - Verify Vercel preview deploys still upload source maps to Sentry ## Summary by CodeRabbit * **Chores** * Refined configuration so error-tracking is enabled only in the designated deployment environment (adds an additional environment check). * Adjusted build-tooling to be conditionally enabled on the platform flag, and ensured non-tracked builds export the platform-aware configuration consistently. --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> --- apps/studio/next.config.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/studio/next.config.js b/apps/studio/next.config.js index 000ca88984b..7b865278390 100644 --- a/apps/studio/next.config.js +++ b/apps/studio/next.config.js @@ -613,9 +613,12 @@ const nextConfig = { // Make sure adding Sentry options is the last code to run before exporting, to // ensure that your source maps include changes from all other Webpack plugins +const platformConfig = + process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' ? withBundleAnalyzer(nextConfig) : nextConfig + module.exports = - process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' - ? withSentryConfig(withBundleAnalyzer(nextConfig), { + process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' && process.env.VERCEL === '1' + ? withSentryConfig(platformConfig, { silent: true, // For all available options, see: @@ -647,4 +650,4 @@ module.exports = applicationKey: 'supabase-studio', }, }) - : nextConfig + : platformConfig