drive/query/drive_document_count_and_sum_query/mod.rs
1//! Joint count-and-sum executor surface for the AVG no-prove path.
2//!
3//! [`Drive::execute_document_count_and_sum_request`] consumes the same
4//! [`DocumentAverageRequest`] / [`DocumentAverageResponse`] pair used
5//! by the prove path and dispatches to one of three per-mode executors
6//! depending on the resolved [`DocumentSumMode`].
7//!
8//! ## Per-shape execution
9//!
10//! - **`Total` / `PerInValue`** (empty-where, or Equal/`In` on a
11//! `summable + countable` index): point-lookup walk against the
12//! index, decoding `(count, sum)` from each visited `CountSumTree` /
13//! `ProvableCountSumTree` terminator in one call via
14//! [`Element::count_sum_value_or_default`]. One grovedb read per
15//! In branch yields both metrics together.
16//! - **`RangeNoProof` distinct shapes** (`GroupByRange` /
17//! `GroupByCompound` + range on a `rangeAverageable` index): one
18//! grovedb walk against
19//! [`crate::query::drive_document_sum_query::DriveDocumentSumQuery::distinct_sum_path_query`]'s
20//! `ProvableCountProvableSumTree` terminators, emitting one
21//! `(count, sum)` per visited distinct in-range key. Bounded by the
22//! request's `limit` (default falls back to
23//! `drive_config.default_query_limit`, explicit limits are clamped to
24//! `drive_config.max_query_limit`).
25//! - **`RangeNoProof` aggregate shapes** (`Aggregate` / `GroupByIn` +
26//! range): grovedb's combined merk-internal accumulator —
27//! `query_aggregate_count_and_sum` against the PCPS path query —
28//! yielding `(u64, i64)` from a single O(log n) traversal. Compound
29//! `In + range` per-In fans out (≤100 branches per the
30//! `In::in_values()` validator cap) and issues one combined
31//! accumulator call per branch under a shared read transaction.
32//!
33//! ## Routing
34//!
35//! Mode resolution reuses sum's versioned routing table
36//! ([`crate::query::drive_document_sum_query::mode_detection::detect_sum_mode_from_inputs`])
37//! — the routing decision is consensus-relevant and identical for
38//! count, sum, and joint count+sum on the no-prove path, so forking
39//! the table here would invite the drift bug PR #3661 caught (count's
40//! `GroupByCompound` row had diverged from sum's). A trivial
41//! [`AverageMode`] → [`SumMode`] adapter feeds sum's mode detector;
42//! `prove = false` is passed unconditionally because the prove path
43//! never enters this module.
44//!
45//! ## Engine-side primitive note
46//!
47//! grovedb exposes `query_aggregate_count_and_sum` as the combined
48//! no-prove accumulator (proof-side analog
49//! `AggregateCountAndSumOnRange` is what the prove path uses for the
50//! same shape). The aggregate `RangeNoProof` branch routes through it
51//! directly — one merk-internal `(u128, i128)` walk per request,
52//! narrowed to `(u64, i64)` at the grovedb entry. Same cost class
53//! and the same shape the prove path uses, just without the proof
54//! envelope.
55
56#[cfg(feature = "server")]
57pub mod drive_dispatcher;
58
59#[cfg(feature = "server")]
60pub mod executors;