feat: Adding a more lightweight query to pg-meta that just fetches the table names (#44469)

Bug fix & feature

## What is the current behavior?

Customers with large schemas have trouble running:
pg-meta/{ref}/tables?include_columns=false

## What is the new behavior?

In the webhooks view some users with large schemas could not click a
table name as the underlying query times out. This just adds a light
weight query and fetches the table name
## Additional context

Add any other context or screenshots.

## Summary by CodeRabbit

* **Refactor**
* Optimized table name fetching in the database interface by introducing
an enhanced query mechanism that streams table metadata more efficiently
from the database.
This commit is contained in:
Aaron Byrne authored and GitHub committed 2026-04-06 09:57:08 -04:00
1 parent 6be596ea34
commit 205dac33da
3 files changed
+63 -8

No files matched your search

@@ -2,7 +2,7 @@ import type { PostgresTrigger } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import Image from 'next/legacy/image'
import { useEffect, useMemo } from 'react'
import { useEffect } from 'react'
import { UseFormReturn } from 'react-hook-form'
import {
Checkbox_Shadcn_,
@@ -35,7 +35,7 @@ import {
} from '@/components/ui/Forms/FormSection'
import { useAPIKeysQuery } from '@/data/api-keys/api-keys-query'
import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query'
import { useTablesQuery } from '@/data/tables/tables-query'
import { useTableNamesQuery } from '@/data/tables/table-names-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { uuidv4 } from '@/lib/helpers'
@@ -66,16 +66,11 @@ export const FormContents = ({ form, selectedHook }: FormContentsProps) => {
const httpUrl = useWatch_Shadcn_({ control: form.control, name: 'http_url' })
const httpHeaders = useWatch_Shadcn_({ control: form.control, name: 'httpHeaders' })
const { data } = useTablesQuery({
const { data: tables = [] } = useTableNamesQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
})
const tables = useMemo(
() => [...(data ?? [])].sort((a, b) => (a.schema > b.schema ? 0 : -1)),
[data]
)
// Handle auth header auto-add for edge functions
useEffect(() => {
if (!isSuccessEdgeFunctions) return
+1
View File
@@ -1,4 +1,5 @@
export const tableKeys = {
names: (projectRef: string | undefined) => ['projects', projectRef, 'table-names'] as const,
list: (projectRef: string | undefined, schema?: string, includeColumns?: boolean) =>
['projects', projectRef, 'tables', schema, includeColumns].filter(Boolean),
retrieve: (projectRef: string | undefined, name: string, schema: string) =>
@@ -0,0 +1,59 @@
import { useQuery } from '@tanstack/react-query'
import type { UseCustomQueryOptions } from 'types'
import { executeSql, ExecuteSqlError } from '../sql/execute-sql-query'
import { tableKeys } from './keys'
export type TableName = {
id: number
schema: string
name: string
}
export type TableNamesVariables = {
projectRef?: string
connectionString?: string | null
}
const TABLE_NAMES_SQL = /* sql */ `
select
c.oid::int8 as id,
nc.nspname as schema,
c.relname as name
from pg_namespace nc
join pg_class c on nc.oid = c.relnamespace
where c.relkind in ('r', 'p')
and not pg_is_other_temp_schema(nc.oid)
and nc.nspname not in ('information_schema', 'pg_catalog', 'pg_toast')
and (
pg_has_role(c.relowner, 'USAGE')
or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
)
order by nc.nspname, c.relname
`.trim()
export async function getTableNames(
{ projectRef, connectionString }: TableNamesVariables,
signal?: AbortSignal
) {
const { result } = await executeSql<TableName[]>(
{ projectRef, connectionString, sql: TABLE_NAMES_SQL, queryKey: ['table-names'] },
signal
)
return result
}
export type TableNamesData = Awaited<ReturnType<typeof getTableNames>>
export type TableNamesError = ExecuteSqlError
export const useTableNamesQuery = <TData = TableNamesData>(
{ projectRef, connectionString }: TableNamesVariables,
{ enabled = true, ...options }: UseCustomQueryOptions<TableNamesData, TableNamesError, TData> = {}
) =>
useQuery<TableNamesData, TableNamesError, TData>({
queryKey: tableKeys.names(projectRef),
queryFn: ({ signal }) => getTableNames({ projectRef, connectionString }, signal),
enabled: enabled && typeof projectRef !== 'undefined',
...options,
})