/** * Shared OLAP helpers for the v-next Postgres observability domain. * * Translates ClickHouse-flavored OLAP idioms (the v-next spec) into Postgres: * * - `toStartOfInterval(ts, INTERVAL '5 MINUTE')` becomes a portable * epoch-floor expression (`to_timestamp(floor(extract(epoch from ts) / N) * N)`) * so arbitrary 1m / 5m / 15m / 1h / 1d buckets work without TimescaleDB. * On a hypertable Postgres still uses chunk pruning over this expression. * - `quantile(p)(value)` becomes `percentile_cont($p) WITHIN GROUP (ORDER BY value)`. * - `argMax(value, ts)` ("last") becomes `(array_agg(value ORDER BY ts DESC))[1]`. * - `sumIf` / `countDistinctIf` use SQL-standard `FILTER (WHERE …)` aggregates. * * GroupBy resolution mirrors the ClickHouse v-next behavior: typed columns * are quoted directly; unknown keys are treated as label / metadata keys and * accessed with `jsonb ->>`. */ import type { AggregationInterval, AggregationType, MetricDistinctColumn } from '@mastra/core/storage'; import type { FilterAccumulator } from './filters.js'; /** Subset of the ComparePeriod enum we react to. */ export type ComparePeriod = 'previous_period' | 'previous_day' | 'previous_week'; /** Time range slice we reuse from filter args. */ export interface PgDateRange { start?: Date; end?: Date; startExclusive?: boolean; endExclusive?: boolean; } /** * Returns a bucket expression that floors `column` to the start of the * requested interval. The expression is portable across Postgres versions * and works equally on a Timescale hypertable. * * Buckets are UTC-aligned (floor of Unix epoch). A `1d` bucket spans * `00:00:00Z` → `23:59:59Z`, not local midnight. Charts that need * local-day buckets should set the desired offset on the time-range filter * rather than expect this helper to honor a session timezone. */ export declare function bucketSql(column: string, interval: AggregationInterval): string; /** SQL aggregate for metric queries, including metric-specific distinct counts. */ export declare function metricAggregationSql(agg: AggregationType, measure: string, timestampColumn?: string, distinctColumn?: MetricDistinctColumn): string; /** SQL aggregate for the standard agg types over a numeric column. */ export declare function aggregationSql(agg: AggregationType, measure: string, timestampColumn?: string): string; export interface ResolvedGroupBy { /** The key the caller asked for. Echoed back in dimensions. */ requestedKey: string; /** SQL alias used for the column in SELECT / GROUP BY. */ alias: string; /** The select expression (e.g. `"labels" ->> $1 AS group_by_0`). */ selectSql: string; /** The bare SQL value expression (used in WHERE for label-exclusion). */ valueSql: string; } /** * Resolves a list of groupBy keys against the set of typed columns for a * signal table. Unknown keys are treated as JSONB lookups against * `labelsColumn` (default `"labels"`) — used by metrics breakdowns. * * Throws when a key is structurally invalid (not SQL-safe) or matches an * excluded column type (jsonb / text[]). */ export declare function resolveGroupBy(acc: FilterAccumulator, groupBy: string[], options: { typedColumns: Set; excludedColumns?: Set; labelsColumn?: string; }): ResolvedGroupBy[]; /** Adds WHERE clauses that exclude rows missing a requested label key. */ export declare function pushLabelExclusions(acc: FilterAccumulator, resolved: ResolvedGroupBy[]): void; export declare function dimensionsFromRow(row: Record, resolved: ResolvedGroupBy[]): Record; export declare function seriesNameFromDimensions(values: unknown[]): string; /** Compute the previous-period date range based on the comparePeriod selection. */ export declare function shiftRange(range: PgDateRange, period: ComparePeriod): PgDateRange | null; export declare function changePercent(current: number | null, previous: number | null): number | null; export declare function bucketDate(value: unknown): Date; export declare function validatePercentiles(percentiles: readonly number[]): void; export declare function percentileSelectSql(percentiles: readonly number[], measureSql: string): string; export declare function percentileSeriesFromRows(rows: Record[], percentiles: readonly number[]): { percentile: number; points: { timestamp: Date; value: number; }[]; }[]; export declare function collectSeriesByDimensions, Entry>(rows: Row[], resolved: ResolvedGroupBy[], createEntry: (dimensionValues: unknown[]) => Entry, appendRow: (entry: Entry, row: Row, dimensionValues: unknown[]) => void): Entry[]; export interface CostSummary { estimatedCost: number | null; costUnit: string | null; } /** SQL for the (estimatedCost, costUnit) pair embedded in metric OLAP responses. */ export declare const COST_SUMMARY_SELECT = "\n SUM(\"estimatedCost\") FILTER (WHERE \"estimatedCost\" IS NOT NULL) AS \"agg_estimatedCost\",\n CASE\n WHEN COUNT(DISTINCT \"costUnit\") FILTER (WHERE \"costUnit\" IS NOT NULL) = 1\n THEN MIN(\"costUnit\") FILTER (WHERE \"costUnit\" IS NOT NULL)\n ELSE NULL\n END AS \"agg_costUnit\"\n"; export declare function costSummaryFromRow(row: Record): CostSummary; export declare const COMPLEX_GROUP_BY_EXCLUDED: Set; //# sourceMappingURL=olap.d.ts.map