mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
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:
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,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,
|
||||
})
|
||||
Reference in new issue
Block a user