open_pql/pql_parser/ast/
from_clause.rs

1use super::*;
2
3#[derive(PartialEq, Eq, Debug, Default)]
4pub struct FromClause<'i> {
5    pub inner: FxHashMap<String, FromItem<'i>>,
6}
7
8impl<'i> FromClause<'i> {
9    pub(crate) fn new<T: IntoIterator<Item = FromItem<'i>>>(
10        items: T,
11    ) -> ResultE<'i, Self> {
12        let mut res = Self::default();
13
14        for item in items {
15            let key = item.key.inner.to_ascii_lowercase();
16
17            if let Entry::Vacant(e) = res.inner.entry(key) {
18                e.insert(item);
19            } else {
20                return Err(user_err(Error::DuplicatedKeyInFrom(item.key.loc)));
21            }
22        }
23
24        Ok(res)
25    }
26
27    pub(crate) fn get_pql_str(&self, key: &str) -> Option<&Str<'i>> {
28        self.inner.get(key).map(|item| &item.value)
29    }
30}
31
32#[derive(PartialEq, Eq, Debug)]
33pub struct FromItem<'i> {
34    pub key: Ident<'i>,
35    pub value: Str<'i>,
36}
37
38impl<'i, U, V> From<(U, V)> for FromItem<'i>
39where
40    U: Into<Ident<'i>>,
41    V: Into<Str<'i>>,
42{
43    fn from(t: (U, V)) -> Self {
44        Self {
45            key: t.0.into(),
46            value: t.1.into(),
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::{super::super::parser::*, *};
54
55    fn p(s: &str) -> FromClause<'_> {
56        FromClauseParser::new().parse(s).unwrap()
57    }
58
59    fn e(s: &str) -> Error {
60        FromClauseParser::new().parse(s).unwrap_err().into()
61    }
62
63    #[test]
64    fn test_from_clause() {
65        let obj = p("from game='holdem', hero='AA'");
66
67        assert_eq!(obj.inner.keys().len(), 2);
68
69        assert_eq!(
70            obj.inner.get("game").unwrap(),
71            &(("game", (5, 9)), ("holdem", (10, 18))).into(),
72        );
73
74        assert_eq!(
75            obj.inner.get("hero").unwrap(),
76            &(("hero", (20, 24)), ("AA", (25, 29))).into(),
77        );
78    }
79
80    #[test]
81    fn test_from_clause_norm_key() {
82        assert!(
83            p("from GAME=''").inner.contains_key("game"),
84            "should normalize keys"
85        );
86        assert!(!p("from GAME=''").inner.contains_key("GAME"));
87    }
88
89    #[test]
90    fn test_from_clause_dup_key() {
91        assert_eq!(
92            e("from GAME='', game=''"),
93            Error::DuplicatedKeyInFrom((14, 18))
94        );
95    }
96}