MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / plan_aggregate

Function plan_aggregate

nodedb-sql/src/planner/aggregate.rs:18–80  ·  view source on GitHub ↗

Plan an aggregate query (GROUP BY + aggregate functions).

(
    select: &ast::Select,
    table: &ResolvedTable,
    filters: &[Filter],
    _scope: &crate::resolver::columns::TableScope,
    functions: &FunctionRegistry,
    temporal: &TemporalScope,
)

Source from the content-addressed store, hash-verified

16
17/// Plan an aggregate query (GROUP BY + aggregate functions).
18pub fn plan_aggregate(
19 select: &ast::Select,
20 table: &ResolvedTable,
21 filters: &[Filter],
22 _scope: &crate::resolver::columns::TableScope,
23 functions: &FunctionRegistry,
24 temporal: &TemporalScope,
25) -> Result<SqlPlan> {
26 // Detect ROLLUP / CUBE / GROUPING SETS before falling through to plain convert.
27 let grouping_expansion = expand_group_by(&select.group_by)?;
28
29 let (group_by_exprs, grouping_sets) = if let Some(exp) = grouping_expansion {
30 (exp.canonical_keys, Some(exp.grouping_sets))
31 } else {
32 (convert_group_by(&select.group_by)?, None)
33 };
34
35 let mut aggregates = extract_aggregates_from_projection(&select.projection, functions)?;
36 let having = match &select.having {
37 Some(expr) => super::select::convert_where_to_filters(expr)?,
38 None => Vec::new(),
39 };
40
41 // When grouping sets are present, detect GROUPING(col) in the projection and
42 // synthesize AggregateExpr entries so the executor can compute them per-set.
43 if grouping_sets.is_some() {
44 let grouping_aggs = extract_grouping_calls(&select.projection, &group_by_exprs)?;
45 aggregates.extend(grouping_aggs);
46 }
47
48 // Extract timeseries-specific params (bucket interval, group columns) if applicable.
49 let (bucket_interval_ms, group_columns) =
50 extract_timeseries_params(&select.group_by, &select.projection, functions)?;
51
52 let rules = engine_rules::resolve_engine_rules(table.info.engine);
53 let base_plan = rules.plan_aggregate(AggregateParams {
54 collection: table.name.clone(),
55 alias: table.alias.clone(),
56 filters: filters.to_vec(),
57 group_by: group_by_exprs.clone(),
58 aggregates: aggregates.clone(),
59 having: having.clone(),
60 limit: 10000,
61 bucket_interval_ms,
62 group_columns,
63 has_auto_tier: table.info.has_auto_tier,
64 bitemporal: table.info.bitemporal,
65 temporal: *temporal,
66 })?;
67
68 // Wrap the plan to attach grouping sets if present.
69 if let Some(sets) = grouping_sets {
70 return Ok(attach_grouping_sets(
71 base_plan,
72 group_by_exprs,
73 aggregates,
74 having,
75 sets,

Callers 1

plan_selectFunction · 0.85

Calls 12

expand_group_byFunction · 0.85
convert_group_byFunction · 0.85
convert_where_to_filtersFunction · 0.85
extract_grouping_callsFunction · 0.85
resolve_engine_rulesFunction · 0.85
attach_grouping_setsFunction · 0.85
extendMethod · 0.45
plan_aggregateMethod · 0.45
cloneMethod · 0.45
to_vecMethod · 0.45

Tested by

no test coverage detected