koron_query_parser/
destructured_query.rs

1use sqlparser::ast;
2
3use crate::{error::ParseError, unsupported};
4
5pub(crate) struct DestructuredQuery<'a> {
6    pub projection: &'a [ast::SelectItem], //i.e. select clause
7    pub from: &'a [ast::TableWithJoins],   //i.e. from clause
8    pub selection: Option<&'a ast::Expr>,  //i.e. where clause
9}
10
11impl<'a> DestructuredQuery<'a> {
12    pub fn destructure(query: &'a ast::Query) -> Result<Self, ParseError> {
13        let ast::Query {
14            with,
15            body,
16            order_by,
17            limit,
18            offset,
19            fetch,
20            locks,
21            limit_by,
22            for_clause,
23        } = query;
24
25        if with.is_some() {
26            return Err(unsupported!("CTEs (i.e., WITH clause).".to_string()));
27        }
28        if !order_by.is_empty() {
29            return Err(unsupported!("ORDER BY.".to_string()));
30        }
31        if limit.is_some() {
32            return Err(unsupported!("LIMIT.".to_string()));
33        }
34        if offset.is_some() {
35            return Err(unsupported!("OFFSET.".to_string()));
36        }
37        if fetch.is_some() {
38            return Err(unsupported!("FETCH.".to_string()));
39        }
40        if !locks.is_empty() {
41            return Err(unsupported!(format!(
42                "locking clauses (i.e., {}).",
43                locks
44                    .iter()
45                    .map(std::string::ToString::to_string)
46                    .collect::<Vec<String>>()
47                    .join(", ")
48            )));
49        }
50        if !limit_by.is_empty() {
51            return Err(unsupported!(format!(
52                "limit by clauses (i.e., {}).",
53                limit_by
54                    .iter()
55                    .map(std::string::ToString::to_string)
56                    .collect::<Vec<String>>()
57                    .join(", ")
58            )));
59        }
60        if for_clause.is_some() {
61            return Err(unsupported!("FOR clause.".to_string()));
62        }
63
64        Self::destructure_set_expr(body)
65    }
66
67    fn destructure_set_expr(set_expr: &'a ast::SetExpr) -> Result<Self, ParseError> {
68        match set_expr {
69            ast::SetExpr::Select(select) => Self::destructure_select(select),
70            ast::SetExpr::Query(query) => Self::destructure(query),
71            ast::SetExpr::SetOperation { op, .. } => {
72                Err(unsupported!(format!("set operations (i.e., {op}).")))
73            }
74            ast::SetExpr::Values(_) => Err(unsupported!("VALUES.".to_string())),
75            ast::SetExpr::Insert(_) | ast::SetExpr::Update(_) => Err(unsupported!(
76                "statements different from single SELECT statement.".to_string()
77            )),
78            ast::SetExpr::Table(_) => Err(unsupported!(
79                "TABLE (i.e., SELECT * FROM table_name).".to_string()
80            )),
81        }
82    }
83
84    fn destructure_select(select: &'a ast::Select) -> Result<Self, ParseError> {
85        let ast::Select {
86            distinct,
87            top,
88            projection,
89            into,
90            from,
91            lateral_views,
92            selection,
93            group_by,
94            cluster_by,    //Used in HIVE
95            distribute_by, //Used in HIVE
96            sort_by,       //Used in HIVE
97            having,
98            qualify, //Used in Snowflake
99            named_window,
100        } = select;
101
102        if distinct.is_some() {
103            return Err(unsupported!("DISTINCT.".to_string()));
104        }
105        if top.is_some() {
106            return Err(unsupported!("TOP.".to_string()));
107        }
108        if into.is_some() {
109            return Err(unsupported!("SELECT INTO.".to_string()));
110        }
111        if !lateral_views.is_empty() {
112            return Err(unsupported!("LATERAL VIEW.".to_string()));
113        }
114        match group_by {
115            ast::GroupByExpr::All => return Err(unsupported!("ALL.".to_string())),
116            ast::GroupByExpr::Expressions(exp) => {
117                if !exp.is_empty() {
118                    return Err(unsupported!("GROUP BY.".to_string()));
119                }
120            }
121        }
122        if !cluster_by.is_empty() {
123            return Err(unsupported!("CLUSTER BY.".to_string()));
124        }
125        if !distribute_by.is_empty() {
126            return Err(unsupported!("DISTRIBUTE BY.".to_string()));
127        }
128        if !sort_by.is_empty() {
129            return Err(unsupported!("SORT BY.".to_string()));
130        }
131        if having.is_some() {
132            return Err(unsupported!("HAVING.".to_string()));
133        }
134        if qualify.is_some() {
135            return Err(unsupported!("QUALIFY.".to_string()));
136        }
137        if !named_window.is_empty() {
138            return Err(unsupported!(
139                "AS (OVER (PARTITION BY .. ORDER BY .. etc.)).".to_string()
140            ));
141        }
142
143        Ok(Self {
144            projection,
145            from,
146            selection: selection.as_ref(),
147        })
148    }
149}