icydb_core/db/query/fluent/load/
builder.rs1use crate::{
2 db::{
3 DbSession,
4 predicate::{CompareOp, Predicate},
5 query::{
6 builder::aggregate::AggregateExpr,
7 explain::ExplainPlan,
8 expr::{FilterExpr, SortExpr},
9 intent::{CompiledQuery, PlannedQuery, Query, QueryError},
10 },
11 },
12 traits::{EntityKind, SingletonEntity},
13 types::Id,
14 value::Value,
15};
16
17pub struct FluentLoadQuery<'a, E>
26where
27 E: EntityKind,
28{
29 pub(super) session: &'a DbSession<E::Canister>,
30 pub(super) query: Query<E>,
31 pub(super) cursor_token: Option<String>,
32}
33
34impl<'a, E> FluentLoadQuery<'a, E>
35where
36 E: EntityKind,
37{
38 pub(crate) const fn new(session: &'a DbSession<E::Canister>, query: Query<E>) -> Self {
39 Self {
40 session,
41 query,
42 cursor_token: None,
43 }
44 }
45
46 #[must_use]
51 pub const fn query(&self) -> &Query<E> {
52 &self.query
53 }
54
55 pub(super) fn map_query(mut self, map: impl FnOnce(Query<E>) -> Query<E>) -> Self {
56 self.query = map(self.query);
57 self
58 }
59
60 pub(super) fn try_map_query(
61 mut self,
62 map: impl FnOnce(Query<E>) -> Result<Query<E>, QueryError>,
63 ) -> Result<Self, QueryError> {
64 self.query = map(self.query)?;
65 Ok(self)
66 }
67
68 #[must_use]
76 pub fn by_id(mut self, id: Id<E>) -> Self {
77 self.query = self.query.by_id(id.key());
78 self
79 }
80
81 #[must_use]
85 pub fn by_ids<I>(mut self, ids: I) -> Self
86 where
87 I: IntoIterator<Item = Id<E>>,
88 {
89 self.query = self.query.by_ids(ids.into_iter().map(|id| id.key()));
90 self
91 }
92
93 #[must_use]
98 pub fn filter(self, predicate: Predicate) -> Self {
99 self.map_query(|query| query.filter(predicate))
100 }
101
102 pub fn filter_expr(self, expr: FilterExpr) -> Result<Self, QueryError> {
103 self.try_map_query(|query| query.filter_expr(expr))
104 }
105
106 pub fn sort_expr(self, expr: SortExpr) -> Result<Self, QueryError> {
107 self.try_map_query(|query| query.sort_expr(expr))
108 }
109
110 #[must_use]
111 pub fn order_by(self, field: impl AsRef<str>) -> Self {
112 self.map_query(|query| query.order_by(field))
113 }
114
115 #[must_use]
116 pub fn order_by_desc(self, field: impl AsRef<str>) -> Self {
117 self.map_query(|query| query.order_by_desc(field))
118 }
119
120 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
122 let field = field.as_ref().to_owned();
123 self.try_map_query(|query| query.group_by(&field))
124 }
125
126 #[must_use]
128 pub fn aggregate(self, aggregate: AggregateExpr) -> Self {
129 self.map_query(|query| query.aggregate(aggregate))
130 }
131
132 #[must_use]
134 pub fn grouped_limits(self, max_groups: u64, max_group_bytes: u64) -> Self {
135 self.map_query(|query| query.grouped_limits(max_groups, max_group_bytes))
136 }
137
138 pub fn having_group(
140 self,
141 field: impl AsRef<str>,
142 op: CompareOp,
143 value: Value,
144 ) -> Result<Self, QueryError> {
145 let field = field.as_ref().to_owned();
146 self.try_map_query(|query| query.having_group(&field, op, value))
147 }
148
149 pub fn having_aggregate(
151 self,
152 aggregate_index: usize,
153 op: CompareOp,
154 value: Value,
155 ) -> Result<Self, QueryError> {
156 self.try_map_query(|query| query.having_aggregate(aggregate_index, op, value))
157 }
158
159 #[must_use]
165 pub fn limit(self, limit: u32) -> Self {
166 self.map_query(|query| query.limit(limit))
167 }
168
169 #[must_use]
175 pub fn offset(self, offset: u32) -> Self {
176 self.map_query(|query| query.offset(offset))
177 }
178
179 #[must_use]
185 pub fn cursor(mut self, token: impl Into<String>) -> Self {
186 self.cursor_token = Some(token.into());
187 self
188 }
189
190 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
195 self.query.explain()
196 }
197
198 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
199 if let Some(err) = self.cursor_intent_error() {
200 return Err(QueryError::Intent(err));
201 }
202
203 self.query.planned()
204 }
205
206 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
207 if let Some(err) = self.cursor_intent_error() {
208 return Err(QueryError::Intent(err));
209 }
210
211 self.query.plan()
212 }
213}
214
215impl<E> FluentLoadQuery<'_, E>
216where
217 E: EntityKind + SingletonEntity,
218 E::Key: Default,
219{
220 #[must_use]
221 pub fn only(self) -> Self {
222 self.map_query(Query::only)
223 }
224}