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

Function expand_group_by

nodedb-sql/src/planner/grouping_sets.rs:36–143  ·  view source on GitHub ↗

Expand the GROUP BY clause if it contains ROLLUP/CUBE/GROUPING SETS. Returns `None` when the GROUP BY is a plain expression list with no extensions — callers fall back to the existing single-set path.

(group_by: &GroupByExpr)

Source from the content-addressed store, hash-verified

34/// Returns `None` when the GROUP BY is a plain expression list with no
35/// extensions — callers fall back to the existing single-set path.
36pub fn expand_group_by(group_by: &GroupByExpr) -> Result<Option<GroupingSetsExpansion>> {
37 let exprs = match group_by {
38 GroupByExpr::All(_) => return Ok(None),
39 GroupByExpr::Expressions(exprs, _) => exprs,
40 };
41
42 // Check whether any expression is ROLLUP / CUBE / GROUPING SETS.
43 let has_extension = exprs.iter().any(is_grouping_extension);
44 if !has_extension {
45 return Ok(None);
46 }
47
48 // Split into plain columns and the single extension expression.
49 // SQL standard: only one extension per GROUP BY; mixed is allowed but
50 // forms a cross-product with the plain columns.
51 let mut plain_ast: Vec<&ast::Expr> = Vec::new();
52 let mut extension_sets: Option<Vec<Vec<&ast::Expr>>> = None;
53
54 for expr in exprs {
55 match expr {
56 ast::Expr::Rollup(groups) => {
57 if extension_sets.is_some() {
58 return Err(SqlError::Unsupported {
59 detail: "only one ROLLUP/CUBE/GROUPING SETS per GROUP BY is supported"
60 .into(),
61 });
62 }
63 extension_sets = Some(expand_rollup(groups));
64 }
65 ast::Expr::Cube(groups) => {
66 if extension_sets.is_some() {
67 return Err(SqlError::Unsupported {
68 detail: "only one ROLLUP/CUBE/GROUPING SETS per GROUP BY is supported"
69 .into(),
70 });
71 }
72 extension_sets = Some(expand_cube(groups));
73 }
74 ast::Expr::GroupingSets(sets) => {
75 if extension_sets.is_some() {
76 return Err(SqlError::Unsupported {
77 detail: "only one ROLLUP/CUBE/GROUPING SETS per GROUP BY is supported"
78 .into(),
79 });
80 }
81 // GroupingSets: each inner Vec<Expr> is one set.
82 extension_sets = Some(sets.iter().map(|s| s.iter().collect()).collect());
83 }
84 other => {
85 plain_ast.push(other);
86 }
87 }
88 }
89
90 let ext_sets = extension_sets.unwrap_or_default();
91
92 // Build canonical key list: plain columns first, then extension columns
93 // (deduped by display name so identical columns share an index).

Callers 7

rollup_two_colsFunction · 0.85
cube_two_colsFunction · 0.85
grouping_sets_explicitFunction · 0.85
mixed_plain_and_rollupFunction · 0.85
rollup_three_colsFunction · 0.85
plan_aggregateFunction · 0.85

Calls 10

expand_rollupFunction · 0.85
expand_cubeFunction · 0.85
convert_exprFunction · 0.85
collectMethod · 0.80
iterMethod · 0.45
pushMethod · 0.45
lenMethod · 0.45
is_emptyMethod · 0.45
cloneMethod · 0.45
containsMethod · 0.45

Tested by 6

rollup_two_colsFunction · 0.68
cube_two_colsFunction · 0.68
grouping_sets_explicitFunction · 0.68
mixed_plain_and_rollupFunction · 0.68
rollup_three_colsFunction · 0.68