icydb_core/db/query/intent/
query.rs1use crate::{
2 db::{
3 predicate::{CompareOp, MissingRowPolicy, Predicate},
4 query::{
5 builder::aggregate::AggregateExpr,
6 explain::ExplainPlan,
7 expr::{FilterExpr, SortExpr},
8 intent::{
9 LoadSpec, QueryError, QueryMode, access_plan_to_entity_keys, model::QueryModel,
10 },
11 plan::AccessPlannedQuery,
12 },
13 },
14 traits::{EntityKind, SingletonEntity},
15 value::Value,
16};
17use std::marker::PhantomData;
18
19#[derive(Debug)]
37pub struct PlannedQuery<E: EntityKind> {
38 plan: AccessPlannedQuery<E::Key>,
39 _marker: PhantomData<E>,
40}
41
42impl<E: EntityKind> PlannedQuery<E> {
43 #[must_use]
44 pub(in crate::db) const fn new(plan: AccessPlannedQuery<E::Key>) -> Self {
45 Self {
46 plan,
47 _marker: PhantomData,
48 }
49 }
50
51 #[must_use]
52 pub fn explain(&self) -> ExplainPlan {
53 self.plan.explain_with_model(E::MODEL)
54 }
55}
56
57#[derive(Clone, Debug)]
65pub struct CompiledQuery<E: EntityKind> {
66 plan: AccessPlannedQuery<E::Key>,
67 _marker: PhantomData<E>,
68}
69
70impl<E: EntityKind> CompiledQuery<E> {
71 #[must_use]
72 pub(in crate::db) const fn new(plan: AccessPlannedQuery<E::Key>) -> Self {
73 Self {
74 plan,
75 _marker: PhantomData,
76 }
77 }
78
79 #[must_use]
80 pub fn explain(&self) -> ExplainPlan {
81 self.plan.explain_with_model(E::MODEL)
82 }
83
84 #[must_use]
86 #[cfg(test)]
87 pub(crate) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
88 self.plan.projection_spec(E::MODEL)
89 }
90
91 #[must_use]
92 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery<E::Key> {
93 self.plan
94 }
95}
96
97#[derive(Debug)]
98pub struct Query<E: EntityKind> {
99 intent: QueryModel<'static, E::Key>,
100 _marker: PhantomData<E>,
101}
102
103impl<E: EntityKind> Query<E> {
104 #[must_use]
108 pub const fn new(consistency: MissingRowPolicy) -> Self {
109 Self {
110 intent: QueryModel::new(E::MODEL, consistency),
111 _marker: PhantomData,
112 }
113 }
114
115 #[must_use]
117 pub const fn mode(&self) -> QueryMode {
118 self.intent.mode()
119 }
120
121 #[must_use]
122 pub(crate) fn has_explicit_order(&self) -> bool {
123 self.intent.has_explicit_order()
124 }
125
126 #[must_use]
127 pub(crate) const fn has_grouping(&self) -> bool {
128 self.intent.has_grouping()
129 }
130
131 #[must_use]
132 pub(crate) const fn load_spec(&self) -> Option<LoadSpec> {
133 self.intent.load_spec()
134 }
135
136 #[must_use]
138 pub fn filter(mut self, predicate: Predicate) -> Self {
139 self.intent = self.intent.filter(predicate);
140 self
141 }
142
143 pub fn filter_expr(self, expr: FilterExpr) -> Result<Self, QueryError> {
145 let Self { intent, _marker } = self;
146 let intent = intent.filter_expr(expr)?;
147
148 Ok(Self { intent, _marker })
149 }
150
151 pub fn sort_expr(self, expr: SortExpr) -> Result<Self, QueryError> {
153 let Self { intent, _marker } = self;
154 let intent = intent.sort_expr(expr)?;
155
156 Ok(Self { intent, _marker })
157 }
158
159 #[must_use]
161 pub fn order_by(mut self, field: impl AsRef<str>) -> Self {
162 self.intent = self.intent.order_by(field);
163 self
164 }
165
166 #[must_use]
168 pub fn order_by_desc(mut self, field: impl AsRef<str>) -> Self {
169 self.intent = self.intent.order_by_desc(field);
170 self
171 }
172
173 #[must_use]
175 pub fn distinct(mut self) -> Self {
176 self.intent = self.intent.distinct();
177 self
178 }
179
180 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
182 let Self { intent, _marker } = self;
183 let intent = intent.push_group_field(field.as_ref())?;
184
185 Ok(Self { intent, _marker })
186 }
187
188 #[must_use]
190 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
191 self.intent = self.intent.push_group_aggregate(aggregate);
192 self
193 }
194
195 #[must_use]
197 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
198 self.intent = self.intent.grouped_limits(max_groups, max_group_bytes);
199 self
200 }
201
202 pub fn having_group(
204 self,
205 field: impl AsRef<str>,
206 op: CompareOp,
207 value: Value,
208 ) -> Result<Self, QueryError> {
209 let field = field.as_ref().to_owned();
210 let Self { intent, _marker } = self;
211 let intent = intent.push_having_group_clause(&field, op, value)?;
212
213 Ok(Self { intent, _marker })
214 }
215
216 pub fn having_aggregate(
218 self,
219 aggregate_index: usize,
220 op: CompareOp,
221 value: Value,
222 ) -> Result<Self, QueryError> {
223 let Self { intent, _marker } = self;
224 let intent = intent.push_having_aggregate_clause(aggregate_index, op, value)?;
225
226 Ok(Self { intent, _marker })
227 }
228
229 pub(crate) fn by_id(self, id: E::Key) -> Self {
231 let Self { intent, _marker } = self;
232 Self {
233 intent: intent.by_id(id),
234 _marker,
235 }
236 }
237
238 pub(crate) fn by_ids<I>(self, ids: I) -> Self
240 where
241 I: IntoIterator<Item = E::Key>,
242 {
243 let Self { intent, _marker } = self;
244 Self {
245 intent: intent.by_ids(ids),
246 _marker,
247 }
248 }
249
250 #[must_use]
252 pub fn delete(mut self) -> Self {
253 self.intent = self.intent.delete();
254 self
255 }
256
257 #[must_use]
264 pub fn limit(mut self, limit: u32) -> Self {
265 self.intent = self.intent.limit(limit);
266 self
267 }
268
269 #[must_use]
274 pub fn offset(mut self, offset: u32) -> Self {
275 self.intent = self.intent.offset(offset);
276 self
277 }
278
279 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
281 let plan = self.planned()?;
282
283 Ok(plan.explain())
284 }
285
286 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
288 let plan = self.build_plan()?;
289 let _projection = plan.projection_spec(E::MODEL);
290
291 Ok(PlannedQuery::new(plan))
292 }
293
294 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
298 let plan = self.build_plan()?;
299 let _projection = plan.projection_spec(E::MODEL);
300
301 Ok(CompiledQuery::new(plan))
302 }
303
304 fn build_plan(&self) -> Result<AccessPlannedQuery<E::Key>, QueryError> {
306 let plan_value = self.intent.build_plan_model()?;
307 let (logical, access) = plan_value.into_parts();
308 let access = access_plan_to_entity_keys::<E>(E::MODEL, access)?;
309 let plan = AccessPlannedQuery::from_parts(logical, access);
310
311 Ok(plan)
312 }
313}
314
315impl<E> Query<E>
316where
317 E: EntityKind + SingletonEntity,
318 E::Key: Default,
319{
320 pub(crate) fn only(self) -> Self {
322 let Self { intent, _marker } = self;
323
324 Self {
325 intent: intent.only(E::Key::default()),
326 _marker,
327 }
328 }
329}