sql_cli/sql/parser/expressions/
case.rs1use crate::sql::parser::ast::{SimpleWhenBranch, SqlExpression, WhenBranch};
5use crate::sql::parser::lexer::Token;
6use tracing::debug;
7
8use super::{log_parse_decision, trace_parse_entry, trace_parse_exit};
9
10pub fn parse_case_expression<P>(parser: &mut P) -> Result<SqlExpression, String>
13where
14 P: ParseCase + ?Sized,
15{
16 trace_parse_entry("parse_case_expression", parser.current_token());
17
18 parser.consume(Token::Case)?;
20
21 debug!("Starting CASE expression parsing");
22
23 if !matches!(parser.current_token(), Token::When) {
28 debug!("Detected simple CASE syntax");
29 return parse_simple_case_expression(parser);
30 }
31
32 let mut when_branches = Vec::new();
33
34 while matches!(parser.current_token(), Token::When) {
36 log_parse_decision(
37 "parse_case_expression",
38 parser.current_token(),
39 "WHEN clause found, parsing condition and result",
40 );
41
42 parser.advance(); debug!("Parsing WHEN condition");
46 let condition = parser.parse_expression()?;
47
48 parser.consume(Token::Then)?;
50
51 debug!("Parsing THEN result");
53 let result = parser.parse_expression()?;
54
55 when_branches.push(WhenBranch {
56 condition: Box::new(condition),
57 result: Box::new(result),
58 });
59
60 debug!("Added WHEN branch #{}", when_branches.len());
61 }
62
63 if when_branches.is_empty() {
65 return Err("CASE expression must have at least one WHEN clause".to_string());
66 }
67
68 let else_branch = if matches!(parser.current_token(), Token::Else) {
70 log_parse_decision(
71 "parse_case_expression",
72 parser.current_token(),
73 "ELSE clause found, parsing default result",
74 );
75
76 parser.advance(); debug!("Parsing ELSE branch");
78 Some(Box::new(parser.parse_expression()?))
79 } else {
80 debug!("No ELSE branch");
81 None
82 };
83
84 parser.consume(Token::End)?;
86
87 debug!(
88 "Completed CASE expression with {} WHEN branches{}",
89 when_branches.len(),
90 if else_branch.is_some() {
91 " and ELSE"
92 } else {
93 ""
94 }
95 );
96
97 let result = Ok(SqlExpression::CaseExpression {
98 when_branches,
99 else_branch,
100 });
101
102 trace_parse_exit("parse_case_expression", &result);
103 result
104}
105
106fn parse_simple_case_expression<P>(parser: &mut P) -> Result<SqlExpression, String>
109where
110 P: ParseCase + ?Sized,
111{
112 trace_parse_entry("parse_simple_case_expression", parser.current_token());
113
114 debug!("Parsing CASE expression value");
116 let expr = parser.parse_expression()?;
117
118 let mut when_branches = Vec::new();
119
120 while matches!(parser.current_token(), Token::When) {
122 log_parse_decision(
123 "parse_simple_case_expression",
124 parser.current_token(),
125 "WHEN clause found, parsing value and result",
126 );
127
128 parser.advance(); debug!("Parsing WHEN value");
132 let value = parser.parse_expression()?;
133
134 parser.consume(Token::Then)?;
136
137 debug!("Parsing THEN result");
139 let result = parser.parse_expression()?;
140
141 when_branches.push(SimpleWhenBranch {
142 value: Box::new(value),
143 result: Box::new(result),
144 });
145
146 debug!("Added simple WHEN branch #{}", when_branches.len());
147 }
148
149 if when_branches.is_empty() {
151 return Err("Simple CASE expression must have at least one WHEN clause".to_string());
152 }
153
154 let else_branch = if matches!(parser.current_token(), Token::Else) {
156 log_parse_decision(
157 "parse_simple_case_expression",
158 parser.current_token(),
159 "ELSE clause found, parsing default result",
160 );
161
162 parser.advance(); debug!("Parsing ELSE branch");
164 Some(Box::new(parser.parse_expression()?))
165 } else {
166 debug!("No ELSE branch");
167 None
168 };
169
170 parser.consume(Token::End)?;
172
173 debug!(
174 "Completed simple CASE expression with {} WHEN branches{}",
175 when_branches.len(),
176 if else_branch.is_some() {
177 " and ELSE"
178 } else {
179 ""
180 }
181 );
182
183 let result = Ok(SqlExpression::SimpleCaseExpression {
184 expr: Box::new(expr),
185 when_branches,
186 else_branch,
187 });
188
189 trace_parse_exit("parse_simple_case_expression", &result);
190 result
191}
192
193pub trait ParseCase {
195 fn current_token(&self) -> &Token;
196 fn advance(&mut self);
197 fn consume(&mut self, expected: Token) -> Result<(), String>;
198
199 fn parse_expression(&mut self) -> Result<SqlExpression, String>;
201}