risingwave_sqlsmith/sqlreduce/passes/
remove.rs1use risingwave_sqlparser::ast::SetExpr;
16
17use crate::sqlreduce::passes::{Ast, Transform, extract_query, extract_query_mut};
18
19pub struct GroupByRemove;
30
31impl Transform for GroupByRemove {
32 fn name(&self) -> String {
33 "groupby_remove".to_owned()
34 }
35
36 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
37 let mut reduction_points = Vec::new();
38 if let Some(query) = extract_query(&ast)
39 && let SetExpr::Select(select) = &query.body
40 {
41 for i in 0..select.group_by.len() {
42 reduction_points.push(i);
43 }
44 }
45 reduction_points.reverse();
46 reduction_points
47 }
48
49 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
50 if let Some(query) = extract_query_mut(ast)
51 && let SetExpr::Select(select) = &mut query.body
52 {
53 for i in reduction_points {
54 select.group_by.remove(i);
55 }
56 }
57 ast.clone()
58 }
59}
60
61pub struct OrderByRemove;
72
73impl Transform for OrderByRemove {
74 fn name(&self) -> String {
75 "orderby_remove".to_owned()
76 }
77
78 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
79 let mut reduction_points = Vec::new();
80 if let Some(query) = extract_query(&ast) {
81 for i in 0..query.order_by.len() {
82 reduction_points.push(i);
83 }
84 }
85 reduction_points.reverse();
86 reduction_points
87 }
88
89 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
90 if let Some(query) = extract_query_mut(ast) {
91 for i in reduction_points {
92 query.order_by.remove(i);
93 }
94 }
95 ast.clone()
96 }
97}
98
99pub struct WhereRemove;
110
111impl Transform for WhereRemove {
112 fn name(&self) -> String {
113 "where_remove".to_owned()
114 }
115
116 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
117 let mut reduction_points = Vec::new();
118 if let Some(query) = extract_query(&ast)
119 && let SetExpr::Select(select) = &query.body
120 && select.selection.is_some()
121 {
122 reduction_points.push(0);
123 }
124 reduction_points.reverse();
125 reduction_points
126 }
127
128 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
129 if let Some(query) = extract_query_mut(ast)
130 && let SetExpr::Select(select) = &mut query.body
131 {
132 for _ in reduction_points {
133 select.selection = None;
134 }
135 }
136 tracing::info!("where_remove ast: {:?}", ast);
137 ast.clone()
138 }
139}
140
141pub struct FromRemove;
152
153impl Transform for FromRemove {
154 fn name(&self) -> String {
155 "from_remove".to_owned()
156 }
157
158 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
159 let mut reduction_points = Vec::new();
160 if let Some(query) = extract_query(&ast)
161 && let SetExpr::Select(select) = &query.body
162 {
163 for i in 0..select.from.len() {
164 reduction_points.push(i);
165 }
166 }
167 reduction_points.reverse();
168 reduction_points
169 }
170
171 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
172 if let Some(query) = extract_query_mut(ast)
173 && let SetExpr::Select(select) = &mut query.body
174 {
175 for i in reduction_points {
176 select.from.remove(i);
177 }
178 }
179 ast.clone()
180 }
181}
182
183pub struct SelectItemRemove;
194
195impl Transform for SelectItemRemove {
196 fn name(&self) -> String {
197 "select_item_remove".to_owned()
198 }
199
200 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
201 let mut reduction_points = Vec::new();
202 if let Some(query) = extract_query(&ast)
203 && let SetExpr::Select(select) = &query.body
204 {
205 for i in 0..select.projection.len() {
206 reduction_points.push(i);
207 }
208 }
209 reduction_points.reverse();
210 reduction_points
211 }
212
213 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
214 if let Some(query) = extract_query_mut(ast)
215 && let SetExpr::Select(select) = &mut query.body
216 {
217 for i in reduction_points {
218 select.projection.remove(i);
219 }
220 }
221 ast.clone()
222 }
223}
224
225pub struct HavingRemove;
226
227impl Transform for HavingRemove {
228 fn name(&self) -> String {
229 "having_remove".to_owned()
230 }
231
232 fn get_reduction_points(&self, ast: Ast) -> Vec<usize> {
233 let mut reduction_points = Vec::new();
234 if let Some(query) = extract_query(&ast)
235 && let SetExpr::Select(select) = &query.body
236 && select.having.is_some()
237 {
238 reduction_points.push(0);
239 }
240
241 reduction_points.reverse();
242 reduction_points
243 }
244
245 fn apply_on(&self, ast: &mut Ast, reduction_points: Vec<usize>) -> Ast {
246 if let Some(query) = extract_query_mut(ast)
247 && let SetExpr::Select(select) = &mut query.body
248 {
249 for _ in reduction_points {
250 select.having = None;
251 }
252 }
253 ast.clone()
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260 use crate::parse_sql;
261
262 #[test]
263 fn test_groupby_remove_with_single_strategy() {
264 let sql = "SELECT a, COUNT(*) FROM t GROUP BY a, b, c;";
265 let ast = parse_sql(sql);
266 let reduction_points = GroupByRemove.get_reduction_points(ast[0].clone());
267 assert_eq!(reduction_points, vec![2, 1, 0]);
268
269 let new_ast = GroupByRemove.apply_on(&mut ast[0].clone(), reduction_points[..1].to_vec());
270 assert_eq!(
271 new_ast,
272 parse_sql("SELECT a, COUNT(*) FROM t GROUP BY a, b;")[0].clone()
273 );
274 }
275
276 #[test]
277 fn test_groupby_remove_with_multiple_strategy() {
278 let sql = "SELECT a, COUNT(*) FROM t GROUP BY a, b, c;";
279 let ast = parse_sql(sql);
280 let reduction_points = GroupByRemove.get_reduction_points(ast[0].clone());
281 assert_eq!(reduction_points, vec![2, 1, 0]);
282
283 let new_ast = GroupByRemove.apply_on(&mut ast[0].clone(), reduction_points);
284 assert_eq!(new_ast, parse_sql("SELECT a, COUNT(*) FROM t;")[0].clone());
285 }
286
287 #[test]
288 fn test_orderby_remove_with_single_strategy() {
289 let sql = "SELECT a, b FROM t ORDER BY a, b, c;";
290 let ast = parse_sql(sql);
291 let reduction_points = OrderByRemove.get_reduction_points(ast[0].clone());
292 assert_eq!(reduction_points, vec![2, 1, 0]);
293
294 let new_ast = OrderByRemove.apply_on(&mut ast[0].clone(), reduction_points[..1].to_vec());
295 assert_eq!(
296 new_ast,
297 parse_sql("SELECT a, b FROM t ORDER BY a, b;")[0].clone()
298 );
299 }
300
301 #[test]
302 fn test_orderby_remove_with_multiple_strategy() {
303 let sql = "SELECT a, b FROM t ORDER BY a, b, c;";
304 let ast = parse_sql(sql);
305 let reduction_points = OrderByRemove.get_reduction_points(ast[0].clone());
306 assert_eq!(reduction_points, vec![2, 1, 0]);
307
308 let new_ast = OrderByRemove.apply_on(&mut ast[0].clone(), reduction_points);
309 assert_eq!(new_ast, parse_sql("SELECT a, b FROM t;")[0].clone());
310 }
311
312 #[test]
313 fn test_where_remove() {
314 let sql = "SELECT * FROM t WHERE a > 1;";
315 let ast = parse_sql(sql);
316 let reduction_points = WhereRemove.get_reduction_points(ast[0].clone());
317 assert_eq!(reduction_points, vec![0]);
318
319 let new_ast = WhereRemove.apply_on(&mut ast[0].clone(), reduction_points);
320 assert_eq!(new_ast, parse_sql("SELECT * FROM t;")[0].clone());
321 }
322
323 #[test]
324 fn test_from_remove_with_single_strategy() {
325 let sql = "SELECT * FROM t1, t2;";
326 let ast = parse_sql(sql);
327 let reduction_points = FromRemove.get_reduction_points(ast[0].clone());
328 assert_eq!(reduction_points, vec![1, 0]);
329
330 let new_ast = FromRemove.apply_on(&mut ast[0].clone(), reduction_points[..1].to_vec());
331 assert_eq!(new_ast, parse_sql("SELECT * FROM t1;")[0].clone());
332 }
333
334 #[test]
335 fn test_from_remove_with_multiple_strategy() {
336 let sql = "SELECT * FROM t1, t2;";
337 let ast = parse_sql(sql);
338 let reduction_points = FromRemove.get_reduction_points(ast[0].clone());
339 assert_eq!(reduction_points, vec![1, 0]);
340
341 let new_ast = FromRemove.apply_on(&mut ast[0].clone(), reduction_points);
342 assert_eq!(new_ast, parse_sql("SELECT *;")[0].clone());
343 }
344
345 #[test]
346 fn test_select_item_remove() {
347 let sql = "SELECT a, b, c FROM t;";
348 let ast = parse_sql(sql);
349 let reduction_points = SelectItemRemove.get_reduction_points(ast[0].clone());
350 assert_eq!(reduction_points, vec![2, 1, 0]);
351
352 let new_ast =
353 SelectItemRemove.apply_on(&mut ast[0].clone(), reduction_points[..1].to_vec());
354 assert_eq!(new_ast, parse_sql("SELECT a, b FROM t;")[0].clone());
355 }
356
357 #[test]
358 fn test_having_remove() {
359 let sql = "SELECT * FROM t HAVING a > 1;";
360 let ast = parse_sql(sql);
361 let reduction_points = HavingRemove.get_reduction_points(ast[0].clone());
362 assert_eq!(reduction_points, vec![0]);
363
364 let new_ast = HavingRemove.apply_on(&mut ast[0].clone(), reduction_points);
365 assert_eq!(new_ast, parse_sql("SELECT * FROM t;")[0].clone());
366 }
367}