Skip to main content

validate_and_canonicalize_where_clauses

Function validate_and_canonicalize_where_clauses 

Source
pub fn validate_and_canonicalize_where_clauses(
    clauses: Vec<WhereClause>,
    platform_version: &PlatformVersion,
) -> Result<Vec<WhereClause>, Error>
Expand description

Run the system-wide where-clause validator on a structured Vec<WhereClause> and canonicalize same-field range pairs into their between* form. Single source of truth for the aggregate shape contract; called by the count / sum / average / joint dispatchers, the legacy CBOR-decoded count entry, and the SDK count / sum / average proof verifiers.

The validator (WhereClause::group_clauses) rejects:

  • Duplicate Equal clauses on the same field (DuplicateNonGroupableClauseSameField).
  • Multiple In clauses (MultipleInClauses) — rejected here: the shared grammar accepts them for protocol version 14+ document queries, but the aggregate surfaces do not.
  • Multiple non-groupable range clauses (MultipleRangeClauses).
  • Equality + In on the same field, range + equality/In on the same field (DuplicateNonGroupableClauseSameField / InvalidWhereClauseComponents).

Without this validation, downstream DriveDocumentCountQuery::find_countable_index_for_where_clauses collapses repeated fields into a BTreeSet and DriveDocumentCountQuery::point_lookup_count_path_query resolves each index property with a single .find(...) — both of which silently pick the first clause on a duplicated field and return a count for an arbitrarily reduced query rather than rejecting the malformed request.

Exception: MultipleRangeClauses is intentionally tolerated here. The regular-query parser rejects two ranges on different fields wholesale (its callers expect (equal_clauses, in_clause, range_clause) triples), but the count-query path accepts the carrier-aggregate shape (outer_range + inner_ACOR_range on different fields, e.g. G8). Structural validation for that shape lives in DriveDocumentCountQuery::detect_mode (which knows about CountMode::GroupByRange-with-two-ranges and routes to DocumentCountMode::RangeAggregateCarrierProof); replicating it here would be redundant.

After validation, [merge_same_field_range_pairs] collapses [field > A, field < B] (and analogous pairs with >= / <=) into the canonical between* operator that DriveDocumentCountQuery::range_clause_to_query_item knows how to convert into a single QueryItem. The regular-query parser does the same merge before its grouped-triple validation; for aggregate queries we do it explicitly here so callers can pass either the bounded form (e.g. [brand > A, brand < B]) or the pre-merged form (e.g. [brand BetweenExcludeBounds [A, B]]) and get equivalent mode detection downstream. Without this merge, G8a’s natural wire shape (four range clauses, two per field) would slip past the catch-MultipleRangeClauses block above and then get rejected by detect_mode’s range_count > 1 structural check.