import { ArrowDown, ArrowRight, ArrowUp, ChevronDown, ExternalLink, ScanSearch } from 'lucide-react' import { useMemo, type RefObject } from 'react' // eslint-disable-next-line no-restricted-imports import { type Column, type DataGridHandle } from 'react-data-grid' import { Button, cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Tooltip, TooltipContent, TooltipTrigger, } from 'ui' import { CodeBlock } from 'ui-patterns/CodeBlock' import { InfoTooltip } from 'ui-patterns/info-tooltip' import { buildQueryInsightFixPrompt } from '../../QueryPerformance/QueryPerformance.ai' import { QUERY_PERFORMANCE_ROLE_DESCRIPTION } from '../../QueryPerformance/QueryPerformance.constants' import type { ClassifiedQuery } from '../QueryInsightsHealth/QueryInsightsHealth.types' import { ISSUE_DOT_COLORS, ISSUE_ICONS, NON_SORTABLE_COLUMNS, QUERY_INSIGHTS_EXPLORER_COLUMNS, } from '../QueryInsightsTable/QueryInsightsTable.constants' import { formatDuration, getColumnName, getTableName, } from '../QueryInsightsTable/QueryInsightsTable.utils' import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' interface UseQueryInsightsTableColumnsParams { sort: { column: string; order: 'asc' | 'desc' } setSort: (config: { column: string; order: 'asc' | 'desc' } | null) => void timeConsumedWidth: number triageQueryColWidth: number gridRef: RefObject setSelectedRow: (idx: number) => void setSelectedTriageRow: (idx: number | undefined) => void setSheetView: (view: 'details' | 'indexes' | 'explain') => void handleGoToLogs: () => void handleAiSuggestedFix: (item: ClassifiedQuery) => void } export function useQueryInsightsTableColumns({ sort, setSort, timeConsumedWidth, triageQueryColWidth, gridRef, setSelectedRow, setSelectedTriageRow, setSheetView, handleGoToLogs, handleAiSuggestedFix, }: UseQueryInsightsTableColumnsParams): { columns: Column[] triageColumns: Column[] } { const columns = useMemo(() => { return QUERY_INSIGHTS_EXPLORER_COLUMNS.map((col) => { const isSortable = !NON_SORTABLE_COLUMNS.includes(col.id as never) const result: Column = { key: col.id, name: col.name, cellClass: `column-${col.id}`, resizable: true, minWidth: col.id === 'prop_total_time' ? timeConsumedWidth : (col.minWidth ?? 120), sortable: isSortable, headerCellClass: 'first:pl-6 cursor-pointer', renderHeaderCell: () => { return (

{col.name}

{col.description && (

{col.description}

)}
{isSortable && (
) }, renderCell: (props) => { const row = props.row const value = row[col.id] if (col.id === 'query') { const IssueIcon = row.issueType ? ISSUE_ICONS[row.issueType] : null return (
{row.issueType && IssueIcon && (
{row.hint && ( {row.hint} )}
)}
} size="tiny" type="default" onClick={(e: React.MouseEvent) => { e.stopPropagation() setSelectedRow(props.rowIdx) setSheetView('details') gridRef.current?.scrollToCell({ idx: 0, rowIdx: props.rowIdx }) }} className="p-1 shrink-0 -translate-x-2 group-hover:flex hidden" />
) } if (col.id === 'prop_total_time') { const percentage = row.prop_total_time || 0 const totalTime = row.total_time || 0 const fillWidth = Math.min(percentage, 100) return (
{percentage && totalTime ? ( {percentage.toFixed(1)}% / {formatDuration(totalTime)} ) : (

)}
) } if (col.id === 'calls') { return (
{typeof value === 'number' && !isNaN(value) && isFinite(value) ? (

{value.toLocaleString()}

) : (

)}
) } if (col.id === 'max_time' || col.id === 'mean_time' || col.id === 'min_time') { return (
{typeof value === 'number' && !isNaN(value) && isFinite(value) ? (

{Math.round(value).toLocaleString()}ms

) : (

)}
) } if (col.id === 'rows_read') { return (
{typeof value === 'number' && !isNaN(value) && isFinite(value) ? (

{value.toLocaleString()}

) : (

)}
) } if (col.id === 'cache_hit_rate') { const num = typeof value === 'number' ? value : parseFloat(value ?? '0') return (
{typeof num === 'number' && !isNaN(num) && isFinite(num) ? (

{num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, })} %

) : (

)}
) } if (col.id === 'rolname') { return (
{value ? (

{value}

{ QUERY_PERFORMANCE_ROLE_DESCRIPTION.find((r) => r.name === value) ?.description }
) : (

)}
) } if (col.id === 'application_name') { return (
{value ? (

{value}

) : (

)}
) } return null }, } return result }) }, [sort, setSort, timeConsumedWidth, gridRef, setSelectedRow, setSheetView]) const triageColumns = useMemo( (): Column[] => [ { key: 'query', name: 'Query', minWidth: triageQueryColWidth, width: triageQueryColWidth, resizable: true, headerCellClass: 'first:pl-6 cursor-default', renderHeaderCell: () => (

Query

), renderCell: (props) => { const row = props.row as ClassifiedQuery const IssueIcon = row.issueType ? ISSUE_ICONS[row.issueType] : null return (
{row.issueType && IssueIcon && (
)}

{row.queryType ?? '–'} {getTableName(row.query) && ( <> {' '} in {getTableName(row.query)} )} {getColumnName(row.query) && ( <> , {getColumnName(row.query)} )}

{row.hint}

} size="tiny" type="default" onClick={(e: React.MouseEvent) => { e.stopPropagation() setSelectedTriageRow(props.rowIdx) setSheetView('details') }} className="p-1 shrink-0 group-hover:flex hidden" />
) }, }, { key: 'prop_total_time', name: 'Time consumed', minWidth: timeConsumedWidth, resizable: true, cellClass: 'column-prop_total_time', headerCellClass: 'cursor-default', renderHeaderCell: () => (

Time consumed

), renderCell: (props) => { const row = props.row as ClassifiedQuery const percentage = row.prop_total_time || 0 const totalTime = row.total_time || 0 const fillWidth = Math.min(percentage, 100) return (
{percentage && totalTime ? ( {percentage.toFixed(1)}% / {formatDuration(totalTime)} ) : (

)}
) }, }, { key: 'calls', name: 'Calls', minWidth: 90, resizable: true, headerCellClass: 'cursor-default', renderHeaderCell: () => (

Calls

), renderCell: (props) => { const value = (props.row as ClassifiedQuery).calls return (
{typeof value === 'number' && !isNaN(value) && isFinite(value) ? (

{value.toLocaleString()}

) : (

)}
) }, }, { key: 'mean_time', name: 'Mean time', minWidth: 90, resizable: true, headerCellClass: 'cursor-default', renderHeaderCell: () => (

Mean time

), renderCell: (props) => { const value = (props.row as ClassifiedQuery).mean_time return (
{typeof value === 'number' && !isNaN(value) && isFinite(value) ? (

{formatDuration(value)}

) : (

)}
) }, }, { key: 'actions', name: 'Actions', minWidth: 200, resizable: false, headerCellClass: 'cursor-default', renderHeaderCell: () => (

Actions

), renderCell: (props) => { const row = props.row as ClassifiedQuery return (
{!row.issueType && ( )} {row.issueType === 'index' && (
e.stopPropagation()}>
)} {(row.issueType === 'error' || row.issueType === 'slow') && (
e.stopPropagation()}> buildQueryInsightFixPrompt(row).prompt} onOpenAssistant={() => handleAiSuggestedFix(row)} copyLabel="Copy Markdown" additionalDropdownItems={[ { label: 'Go to Logs', icon: , onClick: () => handleGoToLogs(), }, ...(row.issueType === 'slow' ? [ { label: 'Explain', icon: , onClick: () => { setSelectedTriageRow(props.rowIdx) setSheetView('explain') }, }, ] : []), ]} />
)}
) }, }, ], [ triageQueryColWidth, timeConsumedWidth, handleGoToLogs, handleAiSuggestedFix, setSelectedTriageRow, setSheetView, ] ) return { columns, triageColumns } }