1mod combine;
23mod cursor;
24mod fetch;
25mod related;
26mod rows;
27mod write;
28
29pub use cursor::CursorPage;
30pub use fetch::Page;
31pub use related::{Prefetch, Relation};
32
33use crate::db::Db;
34use crate::error::QueryError;
35use crate::expr::{Column, Expr, Ident};
36use crate::model::Model;
37use crate::plan::{DistinctMode, LockMode, OrderDirection, OrderExpr, QueryPlan, SelectExpr};
38use related::{Prefetcher, RelNode};
39use std::marker::PhantomData;
40use std::sync::Arc;
41
42pub struct QuerySet<M: Model> {
44 db: Db,
45 plan: QueryPlan,
46 annotations: Vec<(Ident, Expr)>,
48 default_ordering: bool,
51 empty: bool,
53 related: Vec<RelNode>,
55 prefetches: Vec<Arc<dyn Prefetcher<M>>>,
57 cursor: Option<(cursor::Way, String)>,
59 error: Option<QueryError>,
61 _model: PhantomData<fn() -> M>,
62}
63
64impl<M: Model> Clone for QuerySet<M> {
65 fn clone(&self) -> Self {
66 Self {
67 db: self.db.clone(),
68 plan: self.plan.clone(),
69 annotations: self.annotations.clone(),
70 default_ordering: self.default_ordering,
71 empty: self.empty,
72 related: self.related.clone(),
73 prefetches: self.prefetches.clone(),
74 cursor: self.cursor.clone(),
75 error: self.error.clone(),
76 _model: PhantomData,
77 }
78 }
79}
80
81impl<M: Model> std::fmt::Debug for QuerySet<M> {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 f.debug_struct("QuerySet")
84 .field("model", &M::META.name)
85 .field("plan", &self.plan)
86 .finish_non_exhaustive()
87 }
88}
89
90impl<M: Model> QuerySet<M> {
91 pub fn new(db: &Db) -> Self {
93 let mut plan = QueryPlan::from_table(M::META.table);
94 for (column, direction) in M::META.ordering {
95 plan = plan.order_by(Expr::col(*column), *direction);
96 }
97 Self {
98 db: db.clone(),
99 plan,
100 annotations: Vec::new(),
101 default_ordering: !M::META.ordering.is_empty(),
102 empty: false,
103 related: Vec::new(),
104 prefetches: Vec::new(),
105 cursor: None,
106 error: None,
107 _model: PhantomData,
108 }
109 }
110
111 pub fn db(&self) -> &Db {
113 &self.db
114 }
115
116 pub fn plan(&self) -> &QueryPlan {
118 &self.plan
119 }
120
121 #[must_use]
124 pub fn using(mut self, db: &Db) -> Self {
125 self.db = db.clone();
126 self
127 }
128
129 #[must_use]
131 pub fn with_plan(mut self, f: impl FnOnce(QueryPlan) -> QueryPlan) -> Self {
132 self.plan = f(self.plan);
133 self.settle()
134 }
135
136 fn fail(mut self, message: impl Into<String>) -> Self {
138 self.error
139 .get_or_insert_with(|| QueryError::InvalidPlan(message.into()));
140 self
141 }
142
143 fn ready(&self) -> Result<(), QueryError> {
145 self.error.clone().map_or(Ok(()), Err)
146 }
147
148 fn settle(mut self) -> Self {
151 let plan = std::mem::replace(&mut self.plan, QueryPlan::from_table(""));
152 let mut plan = plan.resolve_relations();
153 let aggregated = plan.having.is_some()
154 || plan
155 .projection
156 .iter()
157 .map(|s| &s.expr)
158 .chain(plan.ordering.iter().map(|o| &o.expr))
159 .any(Expr::contains_aggregate);
160 if aggregated && plan.projection.is_empty() {
161 plan.projection = model_projection::<M>();
162 }
163 plan.grouping = if aggregated {
164 plan.projection
165 .iter()
166 .map(|s| &s.expr)
167 .filter(|e| !e.contains_aggregate() && !e.contains_window())
168 .cloned()
169 .collect()
170 } else {
171 Vec::new()
172 };
173 if !plan.grouping.is_empty() && self.default_ordering {
174 plan.ordering.clear();
175 }
176 self.plan = plan;
177 self
178 }
179
180 fn resolve(&self, mut expr: Expr) -> Expr {
182 inline_annotations(&self.annotations, &mut expr);
183 expr
184 }
185
186 #[must_use]
190 pub fn filter(self, predicate: Expr) -> Self {
191 let predicate = self.resolve(predicate);
192 if predicate.contains_window() {
193 return self.fail("cannot filter on a window function; wrap the query as a subquery");
194 }
195 self.with_plan(|mut plan| {
196 if predicate.contains_aggregate() {
197 plan.having = Some(match plan.having.take() {
198 Some(existing) => existing.and(predicate),
199 None => predicate,
200 });
201 plan
202 } else {
203 plan.filter(predicate)
204 }
205 })
206 }
207
208 #[must_use]
210 pub fn exclude(self, predicate: Expr) -> Self {
211 self.filter(!predicate)
212 }
213
214 #[must_use]
216 pub fn order_by(mut self, terms: impl IntoIterator<Item = OrderExpr>) -> Self {
217 let terms: Vec<OrderExpr> = terms
218 .into_iter()
219 .map(|term| OrderExpr {
220 expr: self.resolve(term.expr),
221 direction: term.direction,
222 })
223 .collect();
224 self.default_ordering = false;
225 self.with_plan(|mut plan| {
226 plan.ordering = terms;
227 plan
228 })
229 }
230
231 #[must_use]
234 pub fn reverse(mut self) -> Self {
235 self.default_ordering = false;
236 let pk = M::META.pk().map(|f| f.column);
237 self.with_plan(|mut plan| {
238 if plan.ordering.is_empty() {
239 plan.ordering.extend(pk.map(|c| Expr::col(c).desc()));
240 return plan;
241 }
242 for term in &mut plan.ordering {
243 term.direction = match term.direction {
244 OrderDirection::Asc => OrderDirection::Desc,
245 OrderDirection::Desc => OrderDirection::Asc,
246 };
247 }
248 plan
249 })
250 }
251
252 #[must_use]
254 pub fn limit(self, n: u64) -> Self {
255 self.with_plan(|p| p.limit(n))
256 }
257
258 #[must_use]
260 pub fn offset(self, n: u64) -> Self {
261 self.with_plan(|p| p.offset(n))
262 }
263
264 #[must_use]
266 pub fn distinct(self) -> Self {
267 self.with_plan(|p| p.distinct(DistinctMode::All))
268 }
269
270 #[must_use]
273 pub fn distinct_on<E: Into<Expr>>(self, exprs: impl IntoIterator<Item = E>) -> Self {
274 let exprs = exprs.into_iter().map(|e| self.resolve(e.into())).collect();
275 self.with_plan(|p| p.distinct(DistinctMode::On(exprs)))
276 }
277
278 #[must_use]
280 pub fn none(mut self) -> Self {
281 self.empty = true;
282 self
283 }
284
285 #[must_use]
288 pub fn aliased(self, alias: impl Into<Ident>) -> Self {
289 let alias = alias.into();
290 self.with_plan(|mut p| {
291 p.source.alias = Some(alias);
292 p
293 })
294 }
295
296 #[must_use]
301 pub fn select_for_update(self) -> Self {
302 self.with_plan(|p| p.lock(LockMode::ForUpdate))
303 }
304
305 #[must_use]
307 pub fn nowait(self) -> Self {
308 self.with_plan(|p| p.lock(LockMode::ForUpdateNoWait))
309 }
310
311 #[must_use]
313 pub fn skip_locked(self) -> Self {
314 self.with_plan(|p| p.lock(LockMode::ForUpdateSkipLocked))
315 }
316
317 #[must_use]
323 pub fn annotate(self, name: impl Into<Ident>, expr: impl Into<Expr>) -> Self {
324 self.name_expression(name.into(), expr.into(), true)
325 }
326
327 #[must_use]
330 pub fn alias(self, name: impl Into<Ident>, expr: impl Into<Expr>) -> Self {
331 self.name_expression(name.into(), expr.into(), false)
332 }
333
334 fn name_expression(mut self, name: Ident, expr: Expr, selected: bool) -> Self {
335 if M::META.column(&name).is_some() || self.annotations.iter().any(|(n, _)| *n == name) {
336 return self.fail(format!("annotation `{name}` clashes with an existing name"));
337 }
338 let expr = self.resolve(expr);
339 self.annotations.push((name.clone(), expr.clone()));
340 self.with_plan(|mut plan| {
341 if selected {
342 if plan.projection.is_empty() {
343 plan.projection = model_projection::<M>();
344 }
345 plan.projection.push(SelectExpr::new(expr, Some(name)));
346 }
347 plan
348 })
349 }
350}
351
352fn model_projection<M: Model>() -> Vec<SelectExpr> {
354 M::META
355 .fields
356 .iter()
357 .map(|f| SelectExpr::new(Expr::col(f.column), None))
358 .collect()
359}
360
361fn inline_annotations(annotations: &[(Ident, Expr)], expr: &mut Expr) {
364 if let Expr::Column(Column { source: None, name }) = expr
365 && let Some((_, annotated)) = annotations.iter().find(|(n, _)| n == name)
366 {
367 *expr = annotated.clone();
368 return;
369 }
370 for child in expr.children_mut() {
371 inline_annotations(annotations, child);
372 }
373}
374
375impl Db {
376 pub fn objects<M: Model>(&self) -> QuerySet<M> {
378 QuerySet::new(self)
379 }
380}