useDbQuery.tsx 2.4 KB

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