WithStatements.utils.test.ts161 lines · main
1import { safeSql } from '@supabase/pg-meta'
2import { describe, expect, it, vi } from 'vitest'
3
4import { transformStatementDataToRows } from './WithStatements.utils'
5
6vi.mock('../IndexAdvisor/index-advisor.utils', () => ({
7 filterProtectedSchemaIndexAdvisorResult: vi.fn((result) => {
8 if (result?._mock_filter_null) return null
9 return result
10 }),
11 queryInvolvesProtectedSchemas: vi.fn((query: string) => {
12 return query?.toLowerCase().includes('auth.')
13 }),
14}))
15
16const makeRow = (overrides: Record<string, any> = {}) => ({
17 query: safeSql`SELECT 1`,
18 rolname: 'postgres',
19 calls: 10,
20 mean_time: 5.0,
21 min_time: 1.0,
22 max_time: 20.0,
23 total_time: 50.0,
24 prop_total_time: 0,
25 rows_read: 100,
26 cache_hit_rate: 0.95,
27 index_advisor_result: null,
28 ...overrides,
29})
30
31describe('transformStatementDataToRows', () => {
32 it('returns empty array for null or empty input', () => {
33 expect(transformStatementDataToRows(null as any)).toEqual([])
34 expect(transformStatementDataToRows([])).toEqual([])
35 })
36
37 it('transforms basic rows correctly', () => {
38 const data = [makeRow()]
39 const result = transformStatementDataToRows(data)
40
41 expect(result).toHaveLength(1)
42 expect(result[0]).toMatchObject({
43 query: 'SELECT 1',
44 rolname: 'postgres',
45 calls: 10,
46 mean_time: 5.0,
47 min_time: 1.0,
48 max_time: 20.0,
49 total_time: 50.0,
50 rows_read: 100,
51 cache_hit_rate: 0.95,
52 })
53 })
54
55 it('preserves zero-valued numeric fields as 0', () => {
56 const data = [
57 makeRow({
58 calls: 0,
59 mean_time: 0,
60 min_time: 0,
61 max_time: 0,
62 total_time: 0,
63 rows_read: 0,
64 cache_hit_rate: 0,
65 }),
66 ]
67 const result = transformStatementDataToRows(data)
68
69 expect(result).toHaveLength(1)
70 expect(result[0].calls).toBe(0)
71 expect(result[0].mean_time).toBe(0)
72 expect(result[0].min_time).toBe(0)
73 expect(result[0].max_time).toBe(0)
74 expect(result[0].total_time).toBe(0)
75 expect(result[0].rows_read).toBe(0)
76 expect(result[0].cache_hit_rate).toBe(0)
77 })
78
79 it('sets rolname to undefined when missing', () => {
80 const data = [makeRow({ rolname: undefined })]
81 const result = transformStatementDataToRows(data)
82 expect(result[0].rolname).toBeUndefined()
83 })
84
85 it('calculates prop_total_time as percentage of total time', () => {
86 const data = [
87 makeRow({ query: safeSql`Q1`, total_time: 75 }),
88 makeRow({ query: safeSql`Q2`, total_time: 25 }),
89 ]
90 const result = transformStatementDataToRows(data)
91
92 expect(result[0].prop_total_time).toBe(75)
93 expect(result[1].prop_total_time).toBe(25)
94 })
95
96 it('handles prop_total_time when total is zero', () => {
97 const data = [makeRow({ total_time: 0 })]
98 const result = transformStatementDataToRows(data)
99 expect(result[0].prop_total_time).toBe(0)
100 })
101
102 it('applies index_advisor_result filtering', () => {
103 const data = [
104 makeRow({
105 index_advisor_result: { index_statements: ['CREATE INDEX ON public.users (id)'] },
106 }),
107 ]
108 const result = transformStatementDataToRows(data)
109
110 expect(result[0].index_advisor_result).toEqual({
111 index_statements: ['CREATE INDEX ON public.users (id)'],
112 })
113 })
114
115 it('sets index_advisor_result to null when source is null', () => {
116 const data = [makeRow({ index_advisor_result: null })]
117 const result = transformStatementDataToRows(data)
118 expect(result[0].index_advisor_result).toBeNull()
119 })
120
121 describe('filterIndexAdvisor mode', () => {
122 it('keeps rows for non-protected schema queries', () => {
123 const data = [makeRow({ query: safeSql`SELECT * FROM public.users` })]
124 const result = transformStatementDataToRows(data, true)
125 expect(result).toHaveLength(1)
126 })
127
128 it('keeps protected-schema rows that have valid recommendations', () => {
129 const data = [
130 makeRow({
131 query: safeSql`SELECT * FROM auth.users`,
132 index_advisor_result: { index_statements: ['CREATE INDEX ON auth.users (id)'] },
133 }),
134 ]
135 const result = transformStatementDataToRows(data, true)
136 expect(result).toHaveLength(1)
137 })
138
139 it('filters out protected-schema rows with no valid recommendations', () => {
140 const data = [
141 makeRow({
142 query: safeSql`SELECT * FROM auth.users`,
143 index_advisor_result: { _mock_filter_null: true },
144 }),
145 ]
146 const result = transformStatementDataToRows(data, true)
147 expect(result).toHaveLength(0)
148 })
149
150 it('does not filter protected-schema rows when filterIndexAdvisor is false', () => {
151 const data = [
152 makeRow({
153 query: safeSql`SELECT * FROM auth.users`,
154 index_advisor_result: { _mock_filter_null: true },
155 }),
156 ]
157 const result = transformStatementDataToRows(data, false)
158 expect(result).toHaveLength(1)
159 })
160 })
161})