@@ -8,8 +8,11 @@ ASAP optimization in [planner layering](../design_docs/proposals/planner-layerin
88inventory containing the original named roots and one ` LocalLogicalTarget ` per
99eligible aggregate measure. Discovery includes operator producers read by
1010scalar roots and expressions. Pointer identity prevents repeated discovery of one
11- shared producer. Inputs with assigned execution timing or ASAP operators are
12- rejected: the input ` LogicalDAG ` contains no ASAP summary choices.
11+ shared producer. Inputs with assigned execution timing or materialization, or
12+ with ASAP operators, are rejected: the input ` LogicalDAG ` contains no ASAP
13+ summary choices or physical annotations. An approximate accuracy requirement
14+ needs epsilon and delta in (0, 1); otherwise enumeration fails with
15+ ` InvalidAccuracy ` , naming the root and measure.
1316
1417## Eligibility
1518
@@ -43,16 +46,22 @@ the target keeps every candidate and records how the predicate is applied:
4346
4447- A measure's own filter is recorded as ` LocalLogicalTarget.filter ` ; only
4548 rows that pass it update the state (` SummaryAgg.filter ` ).
46- - ` HAVING ` is recorded as ` LocalLogicalTarget.having ` . The SQL frontend lowers
47- ` HAVING ` to a ` Filter ` directly above the aggregate, so that ` Filter ` counts,
48- as does the aggregate's own ` having ` . A predicate that reads only ` by(...) `
49- group keys is ` HavingPlacement::BelowAggregate ` : it is pushed below the
50- aggregate as a row predicate, like a measure filter. A predicate that reads
51- aggregate values is ` HavingPlacement::AboveOutput ` : it stays a ` Filter `
52- above the finalize/estimate output, and approximate candidates of the
53- target carry ` guarantee = None ` , since membership near the threshold may
54- change. When several such filters read one shared aggregate,
55- ` AboveOutput ` wins.
49+ - ` HAVING ` is recorded as ` LocalLogicalTarget.having ` , one ` HavingEntry `
50+ (consumer ` Filter ` , predicate, placement) each. Only the adjacent form is
51+ recorded for push-down: the aggregate's own ` having ` (an entry with no
52+ ` Filter ` ) and a ` Filter ` directly above the aggregate, which is how the SQL
53+ frontend lowers ` HAVING ` . A predicate that reads only ` by(...) ` group keys
54+ is ` HavingPlacement::BelowAggregate ` : it is pushed below the aggregate as a
55+ row predicate, like a measure filter. A consumer ` Filter ` 's predicate is
56+ pushed below only when every consumer of the aggregate applies the same
57+ predicate; otherwise another consumer would lose rows. Any other ` HAVING ` ,
58+ and every ` HAVING ` of a global aggregate (no group keys, so its one output
59+ row exists even with no input rows), is ` HavingPlacement::AboveOutput ` : it
60+ stays a ` Filter ` above the finalize/estimate output, and approximate
61+ candidates of the target carry ` guarantee = None ` , since membership near
62+ the threshold may change. A value predicate anywhere above an approximate
63+ output, adjacent or not, gets ` guarantee = None ` through guarantee
64+ propagation (#575 ); multi-level push-down is tracked in #664 .
5665
5766For example, an approximate single-column distinct count offers exact execution,
5867HLL, Theta, KMV and UnivMon; an approximate ` count ` offers its exact ` Count `
@@ -75,6 +84,10 @@ the target's one exact option.
7584Distinct-tuple counts do not acquire single-value UnivMon alternatives; that
7685family is not declared for them, so it is not a pruned candidate.
7786
87+ TopK offers its per-group heap summaries (` CmsWithHeap ` ,
88+ ` CountSketchWithHeap ` ). The grouping-level Hydra candidate ("over all groups")
89+ is not generated in Pass 1 here; it is added in #605 .
90+
7891## Scope
7992
8093The API accepts no empirical cost or accuracy model, runtime capabilities, storage
0 commit comments