openpql_pql_parser/ast/
stmt.rs1use super::{Error, Expr, FromClause, FxHashSet, ResultE, Selector, user_err};
2
3#[derive(PartialEq, Debug)]
5pub struct Stmt<'i> {
6 pub selectors: Vec<Selector<'i>>,
8 pub from: FromClause<'i>,
10 pub where_clause: Option<Expr<'i>>,
12}
13
14fn ensure_uniq_names<'i>(selectors: &[Selector]) -> ResultE<'i, ()> {
15 let mut used = FxHashSet::default();
16
17 for selector in selectors {
18 if let Some(id) = &selector.alias
19 && !used.insert(id.inner.to_ascii_lowercase())
20 {
21 return Err(user_err(Error::DuplicatedSelectorName(id.loc)));
22 }
23 }
24
25 Ok(())
26}
27
28impl<'i> Stmt<'i> {
29 pub fn new(
31 selectors: Vec<Selector<'i>>,
32 from: FromClause<'i>,
33 where_clause: Option<Expr<'i>>,
34 ) -> ResultE<'i, Self> {
35 ensure_uniq_names(&selectors)?;
36
37 Ok(Self {
38 selectors,
39 from,
40 where_clause,
41 })
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::*;
49
50 fn s(s: &str) -> Stmt<'_> {
51 parser::StmtParser::new().parse(s).unwrap()
52 }
53
54 fn e(s: &str) -> Error {
55 parser::StmtParser::new().parse(s).unwrap_err().into()
56 }
57
58 #[test]
59 fn test_stmt() {
60 assert_eq!(s("select avg(_) from _=''").selectors.len(), 1);
61 assert_eq!(s("select avg(_), from _=''").selectors.len(), 1);
62
63 assert_eq!(
64 s("select avg(_) as s1 from _=''").selectors[0].alias,
65 Some(("s1", (17, 19)).into())
66 );
67
68 assert_eq!(
69 e("select avg(_) as s1, avg(_) as s1 from _=''"),
70 Error::DuplicatedSelectorName((31, 33))
71 );
72 }
73
74 #[test]
75 fn test_stmt_where_absent() {
76 let stmt = s("select count(_) from _=''");
77 assert!(stmt.where_clause.is_none());
78 }
79
80 #[test]
81 fn test_stmt_where_present() {
82 let stmt = s("select count(_) from _='' where 1 = 1");
83 assert!(stmt.where_clause.is_some());
84 }
85
86 #[test]
87 fn test_stmt_where_logical() {
88 let _ = s("select count(_) from _='' where 1 = 1 and 2 = 2");
89 let _ = s("select count(_) from _='' where 1 = 1 or 2 = 2");
90 let _ = s("select count(_) from _='' where not 1 = 2");
91 let _ = s("select count(_) from _='' where not 1 = 2 and 1 = 1");
92 }
93}