mirror of
https://github.com/supabase/supabase.git
synced 2026-06-30 04:17:50 -04:00
42ec3c4960
## Context Having a custom report block on the project home page with a SQL that returns a large set of results (e.g > 100k rows) causes a client side crash with "Maximum call stack size exceeded" <img width="400" alt="image" src="https://github.com/user-attachments/assets/e4bb5b73-e114-4687-9d0b-a7bff328167c" /> This is happening due to an array spread in `computeYAxisWidth` in `Math.max` - which am hence opting to use a `reduce` instead to mitigate the problem. Am also opting to apply the same autolimit logic in the SQL editor into the `QueryBlock` here, so that we don't unnecessarily fetch a large dataset in this UI. Added a UI indicator as well if auto limit has been applied (So this also overlaps into dashboard scalability too) <img width="1383" height="465" alt="image" src="https://github.com/user-attachments/assets/08b66398-f3b8-49ce-b4a4-23c91510bd54" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Report query blocks now feature automatic SQL limiting functionality, which restricts query results to a maximum of 100 rows when enabled * When active, query result blocks display an informational notice to users, clearly indicating the row restriction that has been applied <!-- end of auto-generated comment: release notes by coderabbit.ai -->
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { ChartConfig } from '@/components/interfaces/SQLEditor/UtilityPanel/ChartConfig'
|
|
|
|
export const checkHasNonPositiveValues = (data: Record<string, unknown>[], key: string): boolean =>
|
|
data.some((row) => (row[key] as number) <= 0)
|
|
|
|
export const formatYAxisTick = (value: number): string => {
|
|
if (Math.abs(value) >= 1_000_000) {
|
|
const n = value / 1_000_000
|
|
return `${Number.isInteger(n) ? n : n.toFixed(1)}M`
|
|
}
|
|
if (Math.abs(value) >= 1_000) {
|
|
const n = value / 1_000
|
|
return `${Number.isInteger(n) ? n : n.toFixed(1)}K`
|
|
}
|
|
if (value !== 0 && Math.abs(value) < 1) {
|
|
return parseFloat(value.toFixed(2)).toString()
|
|
}
|
|
if (!Number.isInteger(value)) {
|
|
return parseFloat(value.toFixed(1)).toString()
|
|
}
|
|
return String(value)
|
|
}
|
|
|
|
export const computeYAxisWidth = (
|
|
data: Record<string, unknown>[],
|
|
key: string,
|
|
{
|
|
isLogScale = false,
|
|
isPercentage = false,
|
|
}: { isLogScale?: boolean; isPercentage?: boolean } = {}
|
|
): number => {
|
|
if (isLogScale) return 52
|
|
if (isPercentage) return Math.max(36, (3 + 1) * 8) // max tick is "100"
|
|
|
|
const maxMagnitude = data.reduce((max, d) => {
|
|
const magnitude = Math.abs(Number(d[key]) || 0)
|
|
return magnitude > max ? magnitude : max
|
|
}, 0)
|
|
return Math.max(36, (formatYAxisTick(maxMagnitude).length + 1) * 8)
|
|
}
|
|
|
|
export const formatLogTick = (value: number): string => {
|
|
if (value >= 1_000_000)
|
|
return `${(value / 1_000_000).toLocaleString(undefined, { maximumFractionDigits: 1 })}M`
|
|
if (value >= 1_000)
|
|
return `${(value / 1_000).toLocaleString(undefined, { maximumFractionDigits: 1 })}k`
|
|
return value.toLocaleString()
|
|
}
|
|
|
|
export const getCumulativeResults = (results: { rows: any[] }, config: ChartConfig) => {
|
|
if (!results?.rows?.length) {
|
|
return []
|
|
}
|
|
|
|
const cumulativeResults = results.rows.reduce((acc, row) => {
|
|
const prev = acc[acc.length - 1] || {}
|
|
const next = {
|
|
...row,
|
|
[config.yKey]: (prev[config.yKey] || 0) + row[config.yKey],
|
|
}
|
|
return [...acc, next]
|
|
}, [])
|
|
|
|
return cumulativeResults
|
|
}
|