1 | #include "duckdb/optimizer/statistics_propagator.hpp" |
---|---|
2 | #include "duckdb/planner/operator/logical_aggregate.hpp" |
3 | |
4 | namespace duckdb { |
5 | |
6 | unique_ptr<NodeStatistics> StatisticsPropagator::PropagateStatistics(LogicalAggregate &aggr, |
7 | unique_ptr<LogicalOperator> *node_ptr) { |
8 | // first propagate statistics in the child node |
9 | node_stats = PropagateStatistics(node_ptr&: aggr.children[0]); |
10 | |
11 | // handle the groups: simply propagate statistics and assign the stats to the group binding |
12 | aggr.group_stats.resize(new_size: aggr.groups.size()); |
13 | for (idx_t group_idx = 0; group_idx < aggr.groups.size(); group_idx++) { |
14 | auto stats = PropagateExpression(expr&: aggr.groups[group_idx]); |
15 | aggr.group_stats[group_idx] = stats ? stats->ToUnique() : nullptr; |
16 | if (!stats) { |
17 | continue; |
18 | } |
19 | if (aggr.grouping_sets.size() > 1) { |
20 | // aggregates with multiple grouping sets can introduce NULL values to certain groups |
21 | // FIXME: actually figure out WHICH groups can have null values introduced |
22 | stats->Set(StatsInfo::CAN_HAVE_NULL_VALUES); |
23 | continue; |
24 | } |
25 | ColumnBinding group_binding(aggr.group_index, group_idx); |
26 | statistics_map[group_binding] = std::move(stats); |
27 | } |
28 | // propagate statistics in the aggregates |
29 | for (idx_t aggregate_idx = 0; aggregate_idx < aggr.expressions.size(); aggregate_idx++) { |
30 | auto stats = PropagateExpression(expr&: aggr.expressions[aggregate_idx]); |
31 | if (!stats) { |
32 | continue; |
33 | } |
34 | ColumnBinding aggregate_binding(aggr.aggregate_index, aggregate_idx); |
35 | statistics_map[aggregate_binding] = std::move(stats); |
36 | } |
37 | // the max cardinality of an aggregate is the max cardinality of the input (i.e. when every row is a unique group) |
38 | return std::move(node_stats); |
39 | } |
40 | |
41 | } // namespace duckdb |
42 |