Skip to main content

qql_core/ast/statement/
retrieval.rs

1//! Typed AST for retrieval statements (SCROLL, COUNT, FACET).
2
3use super::query::QueryCollection;
4use super::types::*;
5use crate::ast::{FilterExpr, Value};
6use alloc::string::String;
7
8/// `ORDER BY` tail of a `SCROLL` statement (OpenAPI `ScrollRequest.order_by`).
9#[derive(Debug, Clone, PartialEq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct ScrollOrderBy {
12    /// Payload field to sort on.
13    pub field: String,
14    /// Sort direction (`ASC` default).
15    pub direction: OrderDirection,
16    /// Optional paging origin: resume ordering from this payload value
17    /// (OpenAPI `OrderBy.start_from`: integer, float, or datetime string).
18    pub start_from: Option<Value>,
19}
20
21/// `SCROLL FROM <collection> … LIMIT n` — cursor-based point iteration.
22#[derive(Debug, Clone, PartialEq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct ScrollStmt {
25    /// Collection to scroll.
26    pub collection: String,
27    /// Maximum number of points per page.
28    pub limit: u64,
29    /// Optional `WHERE` filter.
30    pub filter: Option<Box<FilterExpr>>,
31    /// `AFTER` cursor — resume scrolling after this point ID.
32    pub after: Option<PointId>,
33    /// Optional `ORDER BY` payload ordering (OpenAPI `order_by`).
34    pub order_by: Option<ScrollOrderBy>,
35    /// `SHARD '<key>'` routing key.
36    pub shard_key: Option<super::ShardKey>,
37    /// Optional `WITH PAYLOAD` selector. Defaults to all payload when `None`.
38    pub with_payload: Option<PayloadSelector>,
39    /// Optional `WITH VECTOR` selector. Defaults to no vectors when `None`.
40    pub with_vector: Option<VectorSelector>,
41    /// Optional limit parameter placeholder (`:limit` or `?`).
42    #[cfg_attr(
43        feature = "serde",
44        serde(default, skip_serializing_if = "Option::is_none")
45    )]
46    pub limit_param: Option<String>,
47    /// Source span of the limit parameter placeholder, if unbound.
48    #[cfg_attr(
49        feature = "serde",
50        serde(default, skip_serializing_if = "Option::is_none")
51    )]
52    pub limit_span: Option<crate::error::Span>,
53}
54
55/// `COUNT FROM <collection> [WHERE …]` statement.
56#[derive(Debug, Clone, PartialEq)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58pub struct CountStmt {
59    /// Collection to count (explicit or inherited).
60    pub collection: QueryCollection,
61    /// Optional `WHERE` filter.
62    pub filter: Option<Box<FilterExpr>>,
63    /// `SHARD '<key>'` routing key.
64    pub shard_key: Option<super::ShardKey>,
65    /// `WITH (exact = …)` — require exact counts.
66    pub exact: Option<bool>,
67}
68
69/// In-database categorical facet aggregation statement (`FACET <key> FROM <collection>`).
70///
71/// Compiles to Qdrant's `/collections/{collection}/facet` endpoint (REST) or `Points.Facet` (gRPC), returning hit counts
72/// per unique value for a payload field without retrieving full point records.
73///
74/// # Supported clauses
75/// - `WHERE`: Optional filter restricting candidate points.
76/// - `LIMIT`: Maximum number of distinct facet values to return.
77/// - `EXACT`: Whether to compute exact distributed counts across shards.
78/// - `SHARD`: Target shard key for tenant-partitioned collections.
79#[derive(Debug, Clone, PartialEq)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
81pub struct FacetStmt {
82    /// Payload field name to aggregate values for.
83    pub key: String,
84    /// Target collection.
85    pub collection: QueryCollection,
86    /// Optional point filter scoping the aggregation.
87    pub filter: Option<Box<FilterExpr>>,
88    /// Maximum number of unique facet hits to return.
89    pub limit: Option<u64>,
90    /// Whether to compute exact distributed counts across shards.
91    pub exact: Option<bool>,
92    /// Optional shard key partition routing.
93    pub shard_key: Option<super::ShardKey>,
94    /// Optional limit parameter placeholder (`:limit` or `?`).
95    #[cfg_attr(
96        feature = "serde",
97        serde(default, skip_serializing_if = "Option::is_none")
98    )]
99    pub limit_param: Option<String>,
100    /// Source span of the limit parameter placeholder, if unbound.
101    #[cfg_attr(
102        feature = "serde",
103        serde(default, skip_serializing_if = "Option::is_none")
104    )]
105    pub limit_span: Option<crate::error::Span>,
106}