mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 09:32:15 +08:00
* policy generation * add ai * refactor * table create performance * policy list * style * simplify * refactor * flag * tracking * track * ts * fixes * connection string * re-add rls and realtime toggle * restore old logic * base path * badge * false rls * copy * add permissions button * Refactor based on comments * Fix TS * More nudge * Update tests * Fix test * Fixx * Fix * Address feedback * Address issues * Improve experiment telemetry for generate policies A/B test (#41172) * Address code rabbit catch --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Sean Oliver <882952+seanoliver@users.noreply.github.com>
158 lines
4.3 KiB
TypeScript
158 lines
4.3 KiB
TypeScript
import { QueryClient, useQuery } from '@tanstack/react-query'
|
|
|
|
import { UseCustomQueryOptions } from 'types'
|
|
import { executeSql, ExecuteSqlError } from '../sql/execute-sql-query'
|
|
import { databaseKeys } from './keys'
|
|
|
|
type GetForeignKeyConstraintsVariables = {
|
|
schema?: string
|
|
}
|
|
|
|
export type ForeignKeyConstraintRaw = {
|
|
id: number
|
|
constraint_name: string
|
|
deletion_action: string
|
|
update_action: string
|
|
source_id: string
|
|
source_schema: string
|
|
source_table: string
|
|
source_columns: string
|
|
target_id: string
|
|
target_schema: string
|
|
target_table: string
|
|
target_columns: string
|
|
}
|
|
|
|
export type ForeignKeyConstraint = {
|
|
id: number
|
|
constraint_name: string
|
|
deletion_action: string
|
|
update_action: string
|
|
source_id: number
|
|
source_schema: string
|
|
source_table: string
|
|
source_columns: string[]
|
|
target_id: number
|
|
target_schema: string
|
|
target_table: string
|
|
target_columns: string[]
|
|
}
|
|
|
|
export const getForeignKeyConstraintsSql = ({ schema }: GetForeignKeyConstraintsVariables) => {
|
|
if (!schema) throw new Error('schema is required')
|
|
|
|
const sql = /* SQL */ `
|
|
SELECT
|
|
con.oid as id,
|
|
con.conname as constraint_name,
|
|
con.confdeltype as deletion_action,
|
|
con.confupdtype as update_action,
|
|
rel.oid as source_id,
|
|
nsp.nspname as source_schema,
|
|
rel.relname as source_table,
|
|
(
|
|
SELECT
|
|
array_agg(
|
|
att.attname
|
|
ORDER BY
|
|
un.ord
|
|
)
|
|
FROM
|
|
unnest(con.conkey) WITH ORDINALITY un (attnum, ord)
|
|
INNER JOIN pg_attribute att ON att.attnum = un.attnum
|
|
WHERE
|
|
att.attrelid = rel.oid
|
|
) source_columns,
|
|
frel.oid as target_id,
|
|
fnsp.nspname as target_schema,
|
|
frel.relname as target_table,
|
|
(
|
|
SELECT
|
|
array_agg(
|
|
att.attname
|
|
ORDER BY
|
|
un.ord
|
|
)
|
|
FROM
|
|
unnest(con.confkey) WITH ORDINALITY un (attnum, ord)
|
|
INNER JOIN pg_attribute att ON att.attnum = un.attnum
|
|
WHERE
|
|
att.attrelid = frel.oid
|
|
) target_columns
|
|
FROM
|
|
pg_constraint con
|
|
INNER JOIN pg_class rel ON rel.oid = con.conrelid
|
|
INNER JOIN pg_namespace nsp ON nsp.oid = rel.relnamespace
|
|
INNER JOIN pg_class frel ON frel.oid = con.confrelid
|
|
INNER JOIN pg_namespace fnsp ON fnsp.oid = frel.relnamespace
|
|
WHERE
|
|
con.contype = 'f'
|
|
AND nsp.nspname = '${schema}'
|
|
`.trim()
|
|
|
|
return sql
|
|
}
|
|
|
|
export type ForeignKeyConstraintsVariables = GetForeignKeyConstraintsVariables & {
|
|
projectRef?: string
|
|
connectionString?: string | null
|
|
}
|
|
|
|
export async function getForeignKeyConstraints(
|
|
{ projectRef, connectionString, schema }: ForeignKeyConstraintsVariables,
|
|
signal?: AbortSignal
|
|
) {
|
|
const sql = getForeignKeyConstraintsSql({ schema })
|
|
|
|
const { result } = await executeSql(
|
|
{
|
|
projectRef,
|
|
connectionString,
|
|
sql,
|
|
queryKey: ['foreign-key-constraints', schema],
|
|
},
|
|
signal
|
|
)
|
|
|
|
return (result ?? []).map((foreignKey: ForeignKeyConstraintRaw) => {
|
|
return {
|
|
...foreignKey,
|
|
source_columns: foreignKey.source_columns.replace('{', '').replace('}', '').split(','),
|
|
target_columns: foreignKey.target_columns.replace('{', '').replace('}', '').split(','),
|
|
}
|
|
}) as ForeignKeyConstraint[]
|
|
}
|
|
|
|
export type ForeignKeyConstraintsData = Awaited<ReturnType<typeof getForeignKeyConstraints>>
|
|
export type ForeignKeyConstraintsError = ExecuteSqlError
|
|
|
|
export const useForeignKeyConstraintsQuery = <TData = ForeignKeyConstraintsData>(
|
|
{ projectRef, connectionString, schema }: ForeignKeyConstraintsVariables,
|
|
{
|
|
enabled = true,
|
|
...options
|
|
}: UseCustomQueryOptions<ForeignKeyConstraintsData, ForeignKeyConstraintsError, TData> = {}
|
|
) =>
|
|
useQuery<ForeignKeyConstraintsData, ForeignKeyConstraintsError, TData>({
|
|
queryKey: databaseKeys.foreignKeyConstraints(projectRef, schema),
|
|
queryFn: ({ signal }) =>
|
|
getForeignKeyConstraints({ projectRef, connectionString, schema }, signal),
|
|
enabled:
|
|
enabled &&
|
|
typeof projectRef !== 'undefined' &&
|
|
typeof schema !== 'undefined' &&
|
|
schema.length > 0,
|
|
...options,
|
|
})
|
|
|
|
export function prefetchForeignKeyConstraints(
|
|
client: QueryClient,
|
|
{ projectRef, connectionString, schema }: ForeignKeyConstraintsVariables
|
|
) {
|
|
return client.fetchQuery({
|
|
queryKey: databaseKeys.foreignKeyConstraints(projectRef, schema),
|
|
queryFn: ({ signal }) =>
|
|
getForeignKeyConstraints({ projectRef, connectionString, schema }, signal),
|
|
})
|
|
}
|