1use std::marker::PhantomData;
2
3use sofie_core::Result;
4
5use crate::statement::{Criteria, SortKey};
6use crate::{Condition, Read, Sort, Source};
7
8pub struct Query<T: Source> {
9 pub(crate) criteria: Criteria,
10 marker: PhantomData<fn() -> T>,
11}
12
13impl<T: Source> Clone for Query<T> {
14 fn clone(&self) -> Self {
15 Self {
16 criteria: self.criteria.clone(),
17 marker: PhantomData,
18 }
19 }
20}
21
22impl<T: Source> Default for Query<T> {
23 fn default() -> Self {
24 Self {
25 criteria: Criteria::default(),
26 marker: PhantomData,
27 }
28 }
29}
30
31impl<T: Source> Query<T> {
32 #[must_use]
33 pub fn where_(mut self, condition: Condition<T::Base>) -> Self {
34 self.criteria.conditions.push(condition.kind);
35 self
36 }
37
38 #[must_use]
39 pub fn scope(self, scope: impl FnOnce(Self) -> Self) -> Self {
40 scope(self)
41 }
42
43 #[must_use]
44 pub fn order_by(mut self, sort: Sort<T::Base>) -> Self {
45 self.criteria.sorts.push(sort.key);
46 self
47 }
48
49 #[must_use]
51 pub fn latest(mut self) -> Self {
52 self.criteria.sorts.push(SortKey::id(true));
53 self
54 }
55
56 #[must_use]
57 pub fn limit(mut self, limit: u64) -> Self {
58 self.criteria.limit = Some(limit);
59 self
60 }
61
62 pub async fn all(self, read: &Read) -> Result<Vec<T>> {
63 self.criteria.all(read).await
64 }
65
66 pub async fn first(self, read: &Read) -> Result<Option<T>> {
67 Ok(self.limit(1).all(read).await?.into_iter().next())
68 }
69
70 pub async fn count(self, read: &Read) -> Result<u64> {
71 self.criteria.count::<T::Base>(read).await
72 }
73
74 pub async fn exists(self, read: &Read) -> Result<bool> {
75 self.criteria.exists::<T::Base>(read).await
76 }
77
78 #[cfg(feature = "streams")]
79 pub fn stream(self, read: &Read) -> Result<crate::Stream<T>> {
80 crate::Stream::new(self.criteria, read)
81 }
82}
83
84#[cfg(feature = "soft-delete")]
85impl<T: Source> Query<T>
86where
87 T::Base: crate::SoftDeletes,
88{
89 #[must_use]
90 pub fn with_trashed(mut self) -> Self {
91 self.criteria.with_hidden = true;
92 self
93 }
94}