Files
supabase/apps/studio/data/database-columns/database-column-delete-mutation.ts
Aaditya Bhusal b9d22fa237 fix(studio): stale table metadata cache invalidation after table edits (#47541)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

Fixes stale table metadata after saving edits from the table editor
drawer.

Previously, metadata-only table changes, such as column updates, primary
key/foreign key changes, table renames, or schema moves, could leave
cached table data stale. This affected the Database tables list, schema
visualizer, and reopening the edit drawer.

Fixes #47540

## What is the new behavior?

Table metadata caches are now invalidated consistently after table
create, update, delete, column delete, and queue table creation flows.

The Database tables list, schema visualizer, table editor drawer, table
definitions, constraints, foreign keys, table columns, rows, and lint
data now refresh correctly after relevant table metadata changes.

## Additional context


https://github.com/user-attachments/assets/de849710-8d7b-4d8b-af3b-5232154e996b


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Table metadata now refreshes consistently after table creation,
updates, duplication, and deletion.

* **Bug Fixes**
* Improved synchronization for table lists, lint results, constraints,
and row counts after changes.
* Renaming or moving tables now refreshes both the previous and updated
locations.
* Column and queue changes now trigger the appropriate table metadata
updates.

* **Tests**
* Added coverage for metadata refresh behavior across edits, moves,
optional lint updates, and row counts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-08-25 07:43:45 -06:00

80 lines
2.5 KiB
TypeScript

import pgMeta from '@supabase/pg-meta'
import { PGColumn } from '@supabase/pg-meta/src/pg-meta-columns'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { executeSql } from '@/data/sql/execute-sql-mutation'
import { invalidateTableMetadata } from '@/data/tables/table-metadata-invalidation'
import { viewKeys } from '@/data/views/keys'
import type { ResponseError, UseCustomMutationOptions } from '@/types'
export type DatabaseColumnDeleteVariables = {
projectRef: string
connectionString?: string | null
column: Pick<PGColumn, 'id' | 'name' | 'schema' | 'table' | 'table_id'>
cascade?: boolean
}
export async function deleteDatabaseColumn({
projectRef,
connectionString,
column,
cascade = false,
}: DatabaseColumnDeleteVariables) {
const { sql } = pgMeta.columns.remove(column, { cascade })
const { result } = await executeSql<void>({
projectRef,
connectionString,
sql,
queryKey: ['column', 'delete', column.id],
})
return result
}
type DatabaseColumnDeleteData = Awaited<ReturnType<typeof deleteDatabaseColumn>>
export const useDatabaseColumnDeleteMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseCustomMutationOptions<DatabaseColumnDeleteData, ResponseError, DatabaseColumnDeleteVariables>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<DatabaseColumnDeleteData, ResponseError, DatabaseColumnDeleteVariables>({
mutationFn: (vars) => deleteDatabaseColumn(vars),
async onSuccess(data, variables, context) {
const { projectRef, column } = variables
await Promise.all([
// refetch all entities in the sidebar because deleting a column may regenerate a view (and change its id)
invalidateTableMetadata(queryClient, {
projectRef,
schema: column.schema,
tableId: column.table_id,
tableName: column.table,
includeRows: true,
includeLint: true,
}),
// invalidate all views from this schema, not sure if this is needed since you can't actually delete a column
// which has a view dependent on it
queryClient.invalidateQueries({
queryKey: viewKeys.listBySchema(projectRef, [column.schema]),
}),
])
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to delete database column: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
})
}