sql_cli/query_plan/
transformer_adapters.rs1use super::pipeline::ASTTransformer;
7use super::{CTEHoister, ExpressionLifter, InOperatorLifter};
8use crate::sql::parser::ast::SelectStatement;
9use anyhow::Result;
10
11pub struct CTEHoisterTransformer;
13
14impl CTEHoisterTransformer {
15 pub fn new() -> Self {
16 Self
17 }
18}
19
20impl Default for CTEHoisterTransformer {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl ASTTransformer for CTEHoisterTransformer {
27 fn name(&self) -> &str {
28 "CTEHoister"
29 }
30
31 fn description(&self) -> &str {
32 "Hoists nested WITH clauses to top level for efficient execution"
33 }
34
35 fn transform(&mut self, stmt: SelectStatement) -> Result<SelectStatement> {
36 Ok(CTEHoister::hoist_ctes(stmt))
37 }
38}
39
40pub struct ExpressionLifterTransformer {
42 lifter: ExpressionLifter,
43}
44
45impl ExpressionLifterTransformer {
46 pub fn new() -> Self {
47 Self {
48 lifter: ExpressionLifter::new(),
49 }
50 }
51}
52
53impl Default for ExpressionLifterTransformer {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl ASTTransformer for ExpressionLifterTransformer {
60 fn name(&self) -> &str {
61 "ExpressionLifter"
62 }
63
64 fn description(&self) -> &str {
65 "Lifts window functions and column alias dependencies to CTEs"
66 }
67
68 fn transform(&mut self, mut stmt: SelectStatement) -> Result<SelectStatement> {
69 let lifted_ctes = self.lifter.lift_expressions(&mut stmt);
70
71 if !lifted_ctes.is_empty() {
72 tracing::info!("ExpressionLifter generated {} CTE(s)", lifted_ctes.len());
73 }
74
75 Ok(stmt)
76 }
77}
78
79pub struct InOperatorLifterTransformer {
81 lifter: InOperatorLifter,
82}
83
84impl InOperatorLifterTransformer {
85 pub fn new() -> Self {
86 Self {
87 lifter: InOperatorLifter::new(),
88 }
89 }
90}
91
92impl Default for InOperatorLifterTransformer {
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98impl ASTTransformer for InOperatorLifterTransformer {
99 fn name(&self) -> &str {
100 "InOperatorLifter"
101 }
102
103 fn description(&self) -> &str {
104 "Optimizes IN expressions with large value lists by lifting to CTEs"
105 }
106
107 fn transform(&mut self, mut stmt: SelectStatement) -> Result<SelectStatement> {
108 if self.lifter.rewrite_query(&mut stmt) {
109 tracing::info!("InOperatorLifter applied - query rewritten with CTEs");
110 }
111 Ok(stmt)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_cte_hoister_transformer() {
121 let mut transformer = CTEHoisterTransformer::new();
122 assert_eq!(transformer.name(), "CTEHoister");
123 assert!(transformer.enabled());
124
125 let stmt = SelectStatement::default();
126 let result = transformer.transform(stmt);
127 assert!(result.is_ok());
128 }
129
130 #[test]
131 fn test_expression_lifter_transformer() {
132 let mut transformer = ExpressionLifterTransformer::new();
133 assert_eq!(transformer.name(), "ExpressionLifter");
134
135 let stmt = SelectStatement::default();
136 let result = transformer.transform(stmt);
137 assert!(result.is_ok());
138 }
139
140 #[test]
141 fn test_in_operator_lifter_transformer() {
142 let mut transformer = InOperatorLifterTransformer::new();
143 assert_eq!(transformer.name(), "InOperatorLifter");
144
145 let stmt = SelectStatement::default();
146 let result = transformer.transform(stmt);
147 assert!(result.is_ok());
148 }
149}