mirror of
https://github.com/supabase/supabase.git
synced 2026-06-22 07:22:07 +08:00
## Context Adds a source filter for the query performance advisor so you can filter out queries from the dashboard, or not from the dashboard <img width="309" height="217" alt="image" src="https://github.com/user-attachments/assets/c1fab9af-e57e-482f-afdb-d77a6600edb3" /> For transparency how this works: - Queries fired via the dashboard through the /query endpoint get enriched with metadata from the API to include a comment like `-- source: dashboard` - That's mainly how this filter works atm, to check if this comment exists if the source "Dashboard" is selected, and the inverse if the source "Non dashboard" is selected
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import useDbQuery from 'hooks/analytics/useDbQuery'
|
|
|
|
import { PRESET_CONFIG } from '../Reports/Reports.constants'
|
|
import { Presets } from '../Reports/Reports.types'
|
|
import { QueryPerformanceSQLParams } from './QueryPerformance.types'
|
|
|
|
export function generateQueryPerformanceSql({
|
|
preset,
|
|
orderBy,
|
|
searchQuery = '',
|
|
roles = [],
|
|
sources = [],
|
|
minCalls = 0,
|
|
minTotalTime = 0,
|
|
runIndexAdvisor = false,
|
|
filterIndexAdvisor = false,
|
|
}: QueryPerformanceSQLParams) {
|
|
const queryPerfQueries = PRESET_CONFIG[Presets.QUERY_PERFORMANCE]
|
|
const baseSQL = queryPerfQueries.queries[preset]
|
|
|
|
const orderBySql = orderBy && `ORDER BY ${orderBy.column} ${orderBy.order}`
|
|
|
|
const whereConditions = []
|
|
if (roles.length > 0) {
|
|
whereConditions.push(`auth.rolname in (${roles.map((r) => `'${r}'`).join(', ')})`)
|
|
}
|
|
if (searchQuery.length > 0) {
|
|
whereConditions.push(`statements.query ~* '${searchQuery}'`)
|
|
}
|
|
if (sources.includes('dashboard') && !sources.includes('non-dashboard')) {
|
|
whereConditions.push(`statements.query ~* 'source: dashboard'`)
|
|
}
|
|
if (sources.includes('non-dashboard') && !sources.includes('dashboard')) {
|
|
whereConditions.push(`statements.query !~* 'source: dashboard'`)
|
|
}
|
|
if (minCalls > 0) {
|
|
whereConditions.push(`statements.calls >= ${minCalls}`)
|
|
}
|
|
if (minTotalTime > 0) {
|
|
whereConditions.push(
|
|
`(statements.total_exec_time + statements.total_plan_time) >= ${minTotalTime}`
|
|
)
|
|
}
|
|
|
|
const whereSql = whereConditions.join(' AND ')
|
|
|
|
const sql = baseSQL.sql(
|
|
[],
|
|
whereSql.length > 0 ? `WHERE ${whereSql}` : undefined,
|
|
orderBySql,
|
|
runIndexAdvisor,
|
|
filterIndexAdvisor
|
|
)
|
|
|
|
return { sql, whereSql, orderBySql }
|
|
}
|
|
|
|
export const useQueryPerformanceQuery = (props: QueryPerformanceSQLParams) => {
|
|
const { sql, whereSql, orderBySql } = generateQueryPerformanceSql(props)
|
|
return useDbQuery({ sql, params: undefined, where: whereSql, orderBy: orderBySql })
|
|
}
|