koron_query_parser/
destructured_query.rs1use sqlparser::ast;
2
3use crate::{error::ParseError, unsupported};
4
5pub(crate) struct DestructuredQuery<'a> {
6 pub projection: &'a [ast::SelectItem], pub from: &'a [ast::TableWithJoins], pub selection: Option<&'a ast::Expr>, }
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, distribute_by, sort_by, having,
98 qualify, 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}