MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / plan_aggregate_common

Function plan_aggregate_common

src/sql/src/plan/query.rs:5206–5313  ·  view source on GitHub ↗

Common part of the planning of windowed and non-windowed aggregation functions.

(
    ecx: &ExprContext,
    Function::<Aug> {
        name,
        args,
        filter,
        over: _,
        distinct,
    }: &Function<Aug>,
)

Source from the content-addressed store, hash-verified

5204
5205/// Common part of the planning of windowed and non-windowed aggregation functions.
5206fn plan_aggregate_common(
5207 ecx: &ExprContext,
5208 Function::<Aug> {
5209 name,
5210 args,
5211 filter,
5212 over: _,
5213 distinct,
5214 }: &Function<Aug>,
5215) -> Result<AggregateExpr, PlanError> {
5216 // Normal aggregate functions, like `sum`, expect as input a single expression
5217 // which yields the datum to aggregate. Order sensitive aggregate functions,
5218 // like `jsonb_agg`, are special, and instead expect a Record whose first
5219 // element yields the datum to aggregate and whose successive elements yield
5220 // keys to order by. This expectation is hard coded within the implementation
5221 // of each of the order-sensitive aggregates. The specification of how many
5222 // order by keys to consider, and in what order, is passed via the `order_by`
5223 // field on the `AggregateFunc` variant.
5224
5225 // While all aggregate functions support the ORDER BY syntax, it's a no-op for
5226 // most, so explicitly drop it if the function doesn't care about order. This
5227 // prevents the projection into Record below from triggering on unsupported
5228 // functions.
5229
5230 let impls = match resolve_func(ecx, name, args)? {
5231 Func::Aggregate(impls) => impls,
5232 _ => bail_internal!("plan_aggregate_common called on non-aggregate function"),
5233 };
5234
5235 // We follow PostgreSQL's rule here for mapping `count(*)` into the
5236 // generalized function selection framework. The rule is simple: the user
5237 // must type `count(*)`, but the function selection framework sees an empty
5238 // parameter list, as if the user had typed `count()`. But if the user types
5239 // `count()` directly, that is an error. Like PostgreSQL, we apply these
5240 // rules to all aggregates, not just `count`, since we may one day support
5241 // user-defined aggregates, including user-defined aggregates that take no
5242 // parameters.
5243 let (args, order_by) = match &args {
5244 FunctionArgs::Star => (vec![], vec![]),
5245 FunctionArgs::Args { args, order_by } => {
5246 if args.is_empty() {
5247 sql_bail!(
5248 "{}(*) must be used to call a parameterless aggregate function",
5249 humanize_or_debug(ecx.qcx.scx, name)
5250 );
5251 }
5252 let args = plan_exprs(ecx, args)?;
5253 (args, order_by.clone())
5254 }
5255 };
5256
5257 let (order_by_exprs, col_orders) = plan_function_order_by(ecx, &order_by)?;
5258
5259 let (mut expr, func) = func::select_impl(ecx, FuncSpec::Func(name), impls, args, col_orders)?;
5260 if let Some(filter) = &filter {
5261 // If a filter is present, as in
5262 //
5263 // <agg>(<expr>) FILTER (WHERE <cond>)

Callers 2

plan_select_from_whereFunction · 0.85
plan_functionFunction · 0.85

Calls 15

resolve_funcFunction · 0.85
plan_exprsFunction · 0.85
plan_function_order_byFunction · 0.85
select_implFunction · 0.85
plan_exprFunction · 0.85
if_then_elseFunction · 0.85
type_asMethod · 0.80
is_order_sensitiveMethod · 0.80
FuncEnum · 0.50
is_emptyMethod · 0.45
cloneMethod · 0.45
with_nameMethod · 0.45

Tested by

no test coverage detected