useDbQuery.tsx93 lines · main
1import { type SafeSqlFragment } from '@supabase/pg-meta/src/pg-format'
2import { useQuery } from '@tanstack/react-query'
3
4import { DEFAULT_QUERY_PARAMS } from '@/components/interfaces/Reports/Reports.constants'
5import {
6 BaseReportParams,
7 MetaQueryResponse,
8 ReportQueryDb,
9} from '@/components/interfaces/Reports/Reports.types'
10import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
11import { executeSql } from '@/data/sql/execute-sql-query'
12import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
13import { useDatabaseSelectorStateSnapshot } from '@/state/database-selector'
14
15export interface DbQueryHook<T = any> {
16 isLoading: boolean
17 isRefetching: boolean
18 error: string
19 data: T[]
20 params: BaseReportParams
21 logData?: never
22 runQuery: () => void
23 setParams?: never
24 changeQuery?: never
25 resolvedSql: string
26}
27
28// [Joshen] Atm this is being used only in query performance
29const useDbQuery = ({
30 sql,
31 params = DEFAULT_QUERY_PARAMS,
32 where,
33 orderBy,
34}: {
35 sql: ReportQueryDb['safeSql'] | SafeSqlFragment
36 params?: BaseReportParams
37 where?: string
38 orderBy?: string
39}): DbQueryHook => {
40 const { data: project } = useSelectedProjectQuery()
41 const state = useDatabaseSelectorStateSnapshot()
42
43 const { data: databases } = useReadReplicasQuery({ projectRef: project?.ref })
44 const connectionString = (databases || []).find(
45 (db) => db.identifier === state.selectedDatabaseId
46 )?.connectionString
47 const identifier = state.selectedDatabaseId
48
49 const resolvedSql = typeof sql === 'function' ? sql([]) : sql
50
51 const {
52 data,
53 error: rqError,
54 isPending,
55 isRefetching,
56 refetch,
57 } = useQuery({
58 queryKey: [
59 'projects',
60 project?.ref,
61 'db',
62 { ...params, sql: resolvedSql, identifier },
63 where,
64 orderBy,
65 ],
66 queryFn: ({ signal }) => {
67 return executeSql(
68 {
69 projectRef: project?.ref,
70 connectionString: connectionString || project?.connectionString,
71 sql: resolvedSql,
72 },
73 signal
74 ).then((res) => res.result) as Promise<MetaQueryResponse>
75 },
76 enabled: Boolean(resolvedSql),
77 refetchOnWindowFocus: false,
78 refetchOnReconnect: false,
79 })
80
81 const error = rqError || (typeof data === 'object' ? data?.error : '')
82 return {
83 error,
84 data,
85 isLoading: isPending,
86 isRefetching,
87 params,
88 runQuery: refetch,
89 resolvedSql,
90 }
91}
92
93export default useDbQuery