Skip to main content

coil_data/
query.rs

1use std::fmt;
2
3use crate::{DataModelError, QueryField, require_non_empty};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum SortDirection {
7    Asc,
8    Desc,
9}
10
11impl fmt::Display for SortDirection {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13        match self {
14            Self::Asc => f.write_str("asc"),
15            Self::Desc => f.write_str("desc"),
16        }
17    }
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct QuerySort {
22    pub field: QueryField,
23    pub direction: SortDirection,
24}
25
26impl QuerySort {
27    pub fn ascending(field: impl Into<String>) -> Result<Self, DataModelError> {
28        Ok(Self {
29            field: QueryField::new(field)?,
30            direction: SortDirection::Asc,
31        })
32    }
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum FilterOperator {
37    Eq,
38    Prefix,
39    Range,
40    In,
41}
42
43impl fmt::Display for FilterOperator {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        match self {
46            Self::Eq => f.write_str("eq"),
47            Self::Prefix => f.write_str("prefix"),
48            Self::Range => f.write_str("range"),
49            Self::In => f.write_str("in"),
50        }
51    }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct QueryFilter {
56    pub field: QueryField,
57    pub operator: FilterOperator,
58    pub values: Vec<String>,
59}
60
61impl QueryFilter {
62    pub fn new(
63        field: impl Into<String>,
64        operator: FilterOperator,
65        values: Vec<String>,
66    ) -> Result<Self, DataModelError> {
67        Ok(Self {
68            field: QueryField::new(field)?,
69            operator,
70            values: values
71                .into_iter()
72                .map(|value| require_non_empty("filter_value", value))
73                .collect::<Result<Vec<_>, _>>()?,
74        })
75    }
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub struct PageRequest {
80    pub number: u32,
81    pub size: u16,
82}
83
84impl PageRequest {
85    pub fn new(number: u32, size: u16) -> Result<Self, DataModelError> {
86        if size == 0 {
87            return Err(DataModelError::InvalidPageSize);
88        }
89
90        Ok(Self { number, size })
91    }
92
93    pub fn offset(&self) -> usize {
94        self.number as usize * self.size as usize
95    }
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum PublicationVisibility {
100    PublishedOnly,
101    IncludeDrafts,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum QueryCacheScope {
106    Public,
107    LocaleScoped,
108    UserScoped,
109    Uncacheable,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct QueryContext {
114    pub locale: Option<String>,
115    pub principal_id: Option<String>,
116    pub publication_visibility: PublicationVisibility,
117    pub cache_scope: QueryCacheScope,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
121pub struct QuerySpec {
122    pub filters: Vec<QueryFilter>,
123    pub sort: Vec<QuerySort>,
124    pub page: PageRequest,
125    pub context: QueryContext,
126}
127
128impl QuerySpec {
129    pub fn new(page: PageRequest, context: QueryContext) -> Self {
130        Self {
131            filters: Vec::new(),
132            sort: Vec::new(),
133            page,
134            context,
135        }
136    }
137
138    pub fn with_filter(mut self, filter: QueryFilter) -> Self {
139        self.filters.push(filter);
140        self
141    }
142
143    pub fn with_sort(mut self, sort: QuerySort) -> Self {
144        self.sort.push(sort);
145        self
146    }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq)]
150pub enum DataValue {
151    String(String),
152    Int(i64),
153    UInt(u64),
154    Bool(bool),
155}
156
157impl From<&str> for DataValue {
158    fn from(value: &str) -> Self {
159        Self::String(value.to_string())
160    }
161}
162
163impl From<String> for DataValue {
164    fn from(value: String) -> Self {
165        Self::String(value)
166    }
167}
168
169impl From<i64> for DataValue {
170    fn from(value: i64) -> Self {
171        Self::Int(value)
172    }
173}
174
175impl From<u64> for DataValue {
176    fn from(value: u64) -> Self {
177        Self::UInt(value)
178    }
179}
180
181impl From<bool> for DataValue {
182    fn from(value: bool) -> Self {
183        Self::Bool(value)
184    }
185}
186
187#[derive(Debug, Clone, PartialEq, Eq)]
188pub struct CompiledStatement {
189    pub sql: String,
190    pub bind_values: Vec<DataValue>,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq)]
194pub struct CompiledQuery {
195    pub sql: String,
196    pub bind_values: Vec<DataValue>,
197    pub page: PageRequest,
198    pub context: QueryContext,
199}