Skip to main content

postgrest_parser/ast/
select.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
4#[serde(rename_all = "snake_case")]
5pub enum ItemType {
6    Field,
7    Relation,
8    Spread,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[serde(untagged)]
13pub enum ItemHint {
14    Inner(String),
15    JsonPathCast(Vec<String>, String),
16    JsonPath(Vec<String>),
17    Cast(String),
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub struct SelectItem {
22    pub item_type: ItemType,
23    pub name: String,
24    pub alias: Option<String>,
25    pub children: Option<Vec<SelectItem>>,
26    pub hint: Option<ItemHint>,
27}
28
29impl SelectItem {
30    pub fn field(name: impl Into<String>) -> Self {
31        Self {
32            item_type: ItemType::Field,
33            name: name.into(),
34            alias: None,
35            children: None,
36            hint: None,
37        }
38    }
39
40    pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
41        self.alias = Some(alias.into());
42        self
43    }
44
45    pub fn with_children(mut self, children: Vec<SelectItem>) -> Self {
46        self.children = Some(children);
47        self
48    }
49
50    pub fn with_hint(mut self, hint: ItemHint) -> Self {
51        self.hint = Some(hint);
52        self
53    }
54
55    pub fn relation(name: impl Into<String>) -> Self {
56        Self {
57            item_type: ItemType::Relation,
58            name: name.into(),
59            alias: None,
60            children: None,
61            hint: None,
62        }
63    }
64
65    pub fn spread(name: impl Into<String>) -> Self {
66        Self {
67            item_type: ItemType::Spread,
68            name: name.into(),
69            alias: None,
70            children: None,
71            hint: None,
72        }
73    }
74
75    pub fn wildcard() -> Self {
76        Self::field("*".to_string())
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_select_item_field() {
86        let item = SelectItem::field("id");
87        assert_eq!(item.item_type, ItemType::Field);
88        assert_eq!(item.name, "id");
89        assert!(item.alias.is_none());
90    }
91
92    #[test]
93    fn test_select_item_with_alias() {
94        let item = SelectItem::field("name").with_alias("user_name");
95        assert_eq!(item.alias, Some("user_name".to_string()));
96    }
97
98    #[test]
99    fn test_select_item_with_children() {
100        let item = SelectItem::relation("client")
101            .with_children(vec![SelectItem::field("id"), SelectItem::field("name")]);
102        assert_eq!(item.item_type, ItemType::Relation);
103        assert_eq!(item.children.as_ref().unwrap().len(), 2);
104    }
105
106    #[test]
107    fn test_select_item_wildcard() {
108        let item = SelectItem::wildcard();
109        assert_eq!(item.name, "*");
110        assert_eq!(item.item_type, ItemType::Field);
111    }
112
113    #[test]
114    fn test_select_item_spread() {
115        let item = SelectItem::spread("profile");
116        assert_eq!(item.item_type, ItemType::Spread);
117        assert_eq!(item.name, "profile");
118    }
119
120    #[test]
121    fn test_select_item_serialization() {
122        let item = SelectItem::field("id").with_alias("user_id");
123        let json = serde_json::to_string(&item).unwrap();
124        assert!(json.contains("id"));
125        assert!(json.contains("user_id"));
126    }
127}