import type { IDataQueryPayload, IRow, IViewField, IVisFilter } from '../../interfaces'; import type { IExplainContext } from './types'; /** * Shared workflow-DSL query builders for all explainers. * * Explainers MUST build queries through these helpers: the engine dedupes * structurally identical payloads, so two explainers using the same builder * automatically share one query execution (this is how the contributing- * dimension and unique-mark explainers split a single scan per candidate). */ /** aggregate result key for the per-group row count */ export declare const EXPLAIN_COUNT_KEY = "__explain_row_count"; /** derived-field key used when a quantitative candidate dimension is binned */ export declare const explainBinKey: (fid: string) => string; export declare const QUANT_BIN_NUM = 10; /** measure aggregators whose mass composition is meaningful for D/B class analysis */ export declare const ADDITIVE_SAFE_AGGS: Set; export declare const DEFAULT_CANDIDATE_LIMIT = 20; /** * Candidate dimensions for composition-based explainers: every dimension * field not in the view, capped at ctx.candidateLimit (wide tables would * otherwise trigger one query per field). Temporal candidates are excluded * for now (drill granularity selection is an open question, worklog ยง6.3). */ export declare function complementaryDimensions(ctx: IExplainContext): IViewField[]; /** truncation info so the UI can say "N of M fields scanned" โ€” no silent caps */ export declare function candidateTruncation(ctx: IExplainContext): { scanned: number; total: number; truncated: boolean; }; /** equality filters pinning the selected mark, over the view dimensions */ export declare function markFilters(ctx: IExplainContext): IVisFilter[]; export interface IMarkLevelQuery { payload: IDataQueryPayload; /** the group-by key holding the candidate dimension's (possibly binned) value */ candidateKey: string; } /** * The workhorse query shared by the contributing-dimension and unique-mark * explainers: group by [view dimensions..., candidate] over ALL marks, * fetching row counts plus per-measure sums. Sums and counts are additive, * so mark / siblings / totals are all derivable client-side from this one * result set. */ export declare function markLevelQuery(ctx: IExplainContext, candidate: IViewField): IMarkLevelQuery; /** * Pre-screen aggregates for the selected mark: cheap distribution statistics * that decide whether fetching row-level data is worthwhile. */ export declare function markPrescreenQuery(ctx: IExplainContext, measureFids: string[]): IDataQueryPayload; /** row-level values of the selected mark, for IQR outlier analysis */ export declare function markRawQuery(ctx: IExplainContext, fields: string[], limit: number): IDataQueryPayload; /** * Marks-level aggregation at the view's level of detail, carrying the view * measures plus candidate (unvisualized) measures โ€” the single query behind * the contributing-measure explainer. */ export declare function marksWithMeasuresQuery(ctx: IExplainContext, candidateMeasureFids: string[]): IDataQueryPayload; /** does this aggregated row belong to the selected mark? */ export declare function isMarkRow(row: IRow, ctx: IExplainContext): boolean; /** stable stringify with sorted object keys โ€” the engine's dedup key */ export declare function stableStringify(value: unknown): string;