open_pql/pql_parser/ast/
from_clause.rs1use 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}