Reports.queryPerformance.test.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { describe, expect, it } from 'vitest'
  2. import { PRESET_CONFIG } from './Reports.constants'
  3. import { Presets } from './Reports.types'
  4. const queries = PRESET_CONFIG[Presets.QUERY_PERFORMANCE].queries as Record<
  5. string,
  6. { safeSql: (...args: any[]) => string }
  7. >
  8. const queryNames = [
  9. 'mostFrequentlyInvoked',
  10. 'mostTimeConsuming',
  11. 'slowestExecutionTime',
  12. 'unified',
  13. 'slowQueriesCount',
  14. 'queryMetrics',
  15. ] as const
  16. describe('QUERY_PERFORMANCE SQL queries', () => {
  17. describe('calls > 0 base filter', () => {
  18. it.each(queryNames)('%s includes calls > 0 without user filters', (name) => {
  19. const sql = queries[name].safeSql([], undefined, undefined)
  20. expect(sql).toContain('calls > 0')
  21. })
  22. it.each(queryNames)('%s still includes calls > 0 when user filters are provided', (name) => {
  23. const sql = queries[name].safeSql([], "WHERE auth.rolname in ('postgres')", undefined)
  24. expect(sql).toContain('calls > 0')
  25. })
  26. })
  27. describe('WHERE clause composition with user filters', () => {
  28. const userWhere = "WHERE auth.rolname in ('postgres')"
  29. it.each([
  30. 'mostFrequentlyInvoked',
  31. 'mostTimeConsuming',
  32. 'slowestExecutionTime',
  33. 'unified',
  34. ] as const)('%s: user filters appended with AND (no duplicate WHERE)', (name) => {
  35. const sql = queries[name].safeSql([], userWhere, undefined)
  36. // Should not have two WHERE keywords in a row / duplicate WHERE
  37. expect(sql).not.toMatch(/WHERE\s+.*WHERE/s)
  38. // User filter condition should be present
  39. expect(sql).toContain("auth.rolname in ('postgres')")
  40. // Should use AND to join base filter and user filter
  41. expect(sql).toMatch(/calls > 0\s+AND/)
  42. })
  43. it('queryMetrics: user filters appended with AND (no duplicate WHERE in FROM clause)', () => {
  44. const sql = queries.queryMetrics.safeSql([], userWhere, undefined)
  45. // queryMetrics uses COUNT(*) FILTER (WHERE ...) which is valid SQL and not a duplicate
  46. // Just verify the base filter + user filter are correctly composed
  47. expect(sql).toContain("auth.rolname in ('postgres')")
  48. expect(sql).toMatch(/calls > 0\s+AND/)
  49. // Should not have two WHERE keywords after the FROM keyword
  50. expect(sql).not.toMatch(/FROM[\s\S]*WHERE[\s\S]*WHERE[\s\S]*WHERE/s)
  51. })
  52. it.each([
  53. 'mostFrequentlyInvoked',
  54. 'mostTimeConsuming',
  55. 'slowestExecutionTime',
  56. 'unified',
  57. 'queryMetrics',
  58. ] as const)('%s: no trailing junk when no user filters', (name) => {
  59. const sql = queries[name].safeSql([], undefined, undefined)
  60. // Should not have a dangling undefined or 'WHERE' with nothing after the base filter
  61. expect(sql).not.toContain('undefined')
  62. expect(sql).not.toMatch(/calls > 0\s+AND\s+(ORDER|LIMIT|$)/im)
  63. })
  64. })
  65. describe('slowQueriesCount bug fix', () => {
  66. it('uses table alias "statements"', () => {
  67. const sql = queries.slowQueriesCount.safeSql()
  68. expect(sql).toContain('pg_stat_statements as statements')
  69. })
  70. it('filters by mean_exec_time using the alias', () => {
  71. const sql = queries.slowQueriesCount.safeSql()
  72. expect(sql).toContain('statements.mean_exec_time > 1000')
  73. })
  74. })
  75. describe('window function elimination', () => {
  76. it('unified uses grand_total CTE instead of OVER()', () => {
  77. const sql = queries.unified.safeSql([], undefined, undefined)
  78. expect(sql).toContain('grand_total')
  79. expect(sql).not.toContain('OVER()')
  80. })
  81. it('mostTimeConsuming uses grand_total CTE instead of OVER()', () => {
  82. const sql = queries.mostTimeConsuming.safeSql([], undefined, undefined)
  83. expect(sql).toContain('grand_total')
  84. expect(sql).not.toContain('OVER()')
  85. })
  86. it('grand_total CTE references calls > 0', () => {
  87. const sql = queries.unified.safeSql([], undefined, undefined)
  88. expect(sql).toMatch(/grand_total[\s\S]*calls > 0/)
  89. })
  90. })
  91. describe('multiple user filters', () => {
  92. it('handles multiple user filter conditions', () => {
  93. const multiWhere = "WHERE auth.rolname in ('postgres') AND statements.calls >= 10"
  94. const sql = queries.mostFrequentlyInvoked.safeSql([], multiWhere, undefined)
  95. expect(sql).toContain('calls > 0')
  96. expect(sql).toContain("auth.rolname in ('postgres')")
  97. expect(sql).toContain('statements.calls >= 10')
  98. expect(sql).not.toMatch(/WHERE\s+.*WHERE/s)
  99. })
  100. })
  101. })