Skip to main content

icydb_core/db/query/
read_intent.rs

1//! Module: query::read_intent
2//! Responsibility: hardcoded read-intent caps for public semantic terminals.
3//! Does not own: planner proof, executor routing, or public policy builders.
4//! Boundary: one internal authority for 0.198 engine-owned read-intent limits.
5
6use crate::db::query::admission::{
7    DEFAULT_BOUNDED_READ_MAX_ROWS, DEFAULT_BOUNDED_READ_RESPONSE_BYTES,
8};
9use candid::CandidType;
10use serde::Deserialize;
11
12pub(in crate::db::query) const PUBLIC_PAGE_DEFAULT_ROWS: u32 = DEFAULT_BOUNDED_READ_MAX_ROWS;
13pub(in crate::db::query) const PUBLIC_PAGE_MAX_ROWS: u32 = DEFAULT_BOUNDED_READ_MAX_ROWS;
14pub(in crate::db::query) const PUBLIC_PAGE_MAX_RESPONSE_BYTES: u32 =
15    DEFAULT_BOUNDED_READ_RESPONSE_BYTES;
16
17pub(in crate::db::query) const COMPLETE_SMALL_MAX_ROWS: u32 = DEFAULT_BOUNDED_READ_MAX_ROWS;
18pub(in crate::db::query) const COMPLETE_SMALL_LOOKAHEAD_ROWS: u32 = 1;
19pub(in crate::db::query) const COMPLETE_SMALL_EXECUTION_LIMIT: u32 =
20    COMPLETE_SMALL_MAX_ROWS + COMPLETE_SMALL_LOOKAHEAD_ROWS;
21pub(in crate::db::query) const ADMIN_BATCH_ROWS: u32 = DEFAULT_BOUNDED_READ_MAX_ROWS;
22
23/// Semantic read intent selected by a caller-facing terminal.
24///
25/// This is diagnostic metadata only. It does not grant access, choose planner
26/// routes, or configure admission policy.
27#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
28pub enum ReadIntentKind {
29    /// No semantic read intent was attached to this diagnostic payload.
30    #[default]
31    Unspecified,
32
33    /// Low-level execution over the effective bounded row window.
34    BoundedRowWindow,
35
36    /// Boolean existence check.
37    ExistenceCheck,
38
39    /// Request-owned public cursor page.
40    PublicPage,
41
42    /// Complete small-set read that fails instead of silently truncating.
43    CompleteSmallSet,
44
45    /// Exact count or sum aggregate.
46    ExactAggregate,
47
48    /// Trusted/admin cursor batch with engine-owned batch size.
49    TrustedAdminBatch,
50}
51
52/// Request-owned public page shape.
53///
54/// The requested limit is a caller preference, not a custom policy. IcyDB
55/// clamps it to the engine-owned public page cap before admission/execution.
56#[derive(Clone, Debug, Default, Eq, PartialEq)]
57pub struct PageRequest {
58    limit: Option<u32>,
59    cursor: Option<String>,
60}
61
62impl PageRequest {
63    /// Build a first-page request using the default public page size.
64    #[must_use]
65    pub const fn new() -> Self {
66        Self {
67            limit: None,
68            cursor: None,
69        }
70    }
71
72    /// Build a first-page request with one requested page size.
73    #[must_use]
74    pub const fn first(limit: u32) -> Self {
75        Self {
76            limit: Some(limit),
77            cursor: None,
78        }
79    }
80
81    /// Build a continuation request with one requested page size and cursor.
82    #[must_use]
83    pub fn next(limit: u32, cursor: impl Into<String>) -> Self {
84        Self {
85            limit: Some(limit),
86            cursor: Some(cursor.into()),
87        }
88    }
89
90    /// Return this request with a requested page size.
91    #[must_use]
92    pub const fn with_limit(mut self, limit: u32) -> Self {
93        self.limit = Some(limit);
94        self
95    }
96
97    /// Return this request with an opaque continuation cursor.
98    #[must_use]
99    pub fn with_cursor(mut self, cursor: impl Into<String>) -> Self {
100        self.cursor = Some(cursor.into());
101        self
102    }
103
104    /// Return the caller-requested page size, if supplied.
105    #[must_use]
106    pub const fn limit(&self) -> Option<u32> {
107        self.limit
108    }
109
110    /// Return the opaque continuation cursor, if supplied.
111    #[must_use]
112    pub fn cursor(&self) -> Option<&str> {
113        self.cursor.as_deref()
114    }
115
116    pub(in crate::db::query) const fn effective_limit(&self) -> u32 {
117        match self.limit {
118            Some(0) => 1,
119            Some(limit) if limit > PUBLIC_PAGE_MAX_ROWS => PUBLIC_PAGE_MAX_ROWS,
120            Some(limit) => limit,
121            None => PUBLIC_PAGE_DEFAULT_ROWS,
122        }
123    }
124
125    pub(in crate::db::query) fn into_cursor(self) -> Option<String> {
126        self.cursor
127    }
128}
129
130/// Request-owned trusted/admin batch continuation shape.
131///
132/// The batch size is engine-owned. Callers may only supply an opaque cursor
133/// for continuation, and the terminal remains gated to trusted read lanes.
134#[derive(Clone, Debug, Default, Eq, PartialEq)]
135pub struct AdminBatchRequest {
136    cursor: Option<String>,
137}
138
139impl AdminBatchRequest {
140    /// Build a first-batch request.
141    #[must_use]
142    pub const fn new() -> Self {
143        Self { cursor: None }
144    }
145
146    /// Build a continuation request with an opaque cursor.
147    #[must_use]
148    pub fn next(cursor: impl Into<String>) -> Self {
149        Self {
150            cursor: Some(cursor.into()),
151        }
152    }
153
154    /// Return this request with an opaque continuation cursor.
155    #[must_use]
156    pub fn with_cursor(mut self, cursor: impl Into<String>) -> Self {
157        self.cursor = Some(cursor.into());
158        self
159    }
160
161    /// Return the opaque continuation cursor, if supplied.
162    #[must_use]
163    pub fn cursor(&self) -> Option<&str> {
164        self.cursor.as_deref()
165    }
166
167    pub(in crate::db::query) fn into_cursor(self) -> Option<String> {
168        self.cursor
169    }
170}