Skip to main content

postgrest_parser/ast/
prefer.rs

1use serde::{Deserialize, Serialize};
2
3/// Return representation preference for mutations
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
5#[serde(rename_all = "lowercase")]
6pub enum ReturnRepresentation {
7    /// Return full representation of affected rows
8    #[default]
9    Full,
10    /// Return minimal data (just status)
11    Minimal,
12    /// Return only headers
13    HeadersOnly,
14}
15
16/// Resolution preference for INSERT conflicts
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18#[serde(rename_all = "kebab-case")]
19pub enum Resolution {
20    /// Merge duplicates (upsert)
21    MergeDuplicates,
22    /// Ignore duplicates
23    IgnoreDuplicates,
24}
25
26/// Count preference for SELECT queries
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
28#[serde(rename_all = "lowercase")]
29pub enum Count {
30    /// Exact count (can be slow)
31    Exact,
32    /// Planned count from query planner
33    Planned,
34    /// Estimated count
35    Estimated,
36}
37
38/// Plurality preference for responses
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
40#[serde(rename_all = "lowercase")]
41pub enum Plurality {
42    /// Expect single row
43    Singular,
44    /// Expect multiple rows (default)
45    #[default]
46    Multiple,
47}
48
49/// Missing value handling for INSERT
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
51#[serde(rename_all = "lowercase")]
52pub enum Missing {
53    /// Use column defaults
54    Default,
55    /// Use NULL (default)
56    #[default]
57    Null,
58}
59
60/// PostgREST Prefer header options
61#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
62pub struct PreferOptions {
63    pub return_representation: Option<ReturnRepresentation>,
64    pub resolution: Option<Resolution>,
65    pub count: Option<Count>,
66    pub plurality: Option<Plurality>,
67    pub missing: Option<Missing>,
68}
69
70impl PreferOptions {
71    pub fn new() -> Self {
72        Self {
73            return_representation: None,
74            resolution: None,
75            count: None,
76            plurality: None,
77            missing: None,
78        }
79    }
80
81    pub fn with_return(mut self, ret: ReturnRepresentation) -> Self {
82        self.return_representation = Some(ret);
83        self
84    }
85
86    pub fn with_resolution(mut self, res: Resolution) -> Self {
87        self.resolution = Some(res);
88        self
89    }
90
91    pub fn with_count(mut self, count: Count) -> Self {
92        self.count = Some(count);
93        self
94    }
95
96    pub fn with_plurality(mut self, plurality: Plurality) -> Self {
97        self.plurality = Some(plurality);
98        self
99    }
100
101    pub fn with_missing(mut self, missing: Missing) -> Self {
102        self.missing = Some(missing);
103        self
104    }
105
106    pub fn is_empty(&self) -> bool {
107        self.return_representation.is_none()
108            && self.resolution.is_none()
109            && self.count.is_none()
110            && self.plurality.is_none()
111            && self.missing.is_none()
112    }
113}
114
115impl Default for PreferOptions {
116    fn default() -> Self {
117        Self::new()
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn test_return_representation_default() {
127        assert_eq!(ReturnRepresentation::default(), ReturnRepresentation::Full);
128    }
129
130    #[test]
131    fn test_plurality_default() {
132        assert_eq!(Plurality::default(), Plurality::Multiple);
133    }
134
135    #[test]
136    fn test_missing_default() {
137        assert_eq!(Missing::default(), Missing::Null);
138    }
139
140    #[test]
141    fn test_prefer_options_new() {
142        let opts = PreferOptions::new();
143        assert!(opts.is_empty());
144    }
145
146    #[test]
147    fn test_prefer_options_builder() {
148        let opts = PreferOptions::new()
149            .with_return(ReturnRepresentation::Minimal)
150            .with_count(Count::Exact);
151
152        assert_eq!(
153            opts.return_representation,
154            Some(ReturnRepresentation::Minimal)
155        );
156        assert_eq!(opts.count, Some(Count::Exact));
157        assert!(!opts.is_empty());
158    }
159
160    #[test]
161    fn test_prefer_options_serialization() {
162        let opts = PreferOptions::new()
163            .with_return(ReturnRepresentation::Full)
164            .with_resolution(Resolution::MergeDuplicates);
165
166        let json = serde_json::to_string(&opts).unwrap();
167        assert!(json.contains("full"));
168        assert!(json.contains("merge-duplicates"));
169    }
170}