sql_cli/sql/parser/expressions/
case.rs

1// CASE expression parsing
2// Handles CASE/WHEN/THEN/ELSE/END expressions for conditional logic
3
4use 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
10/// Parse a CASE expression
11/// CASE [expr] WHEN condition THEN result [WHEN ...] [ELSE result] END
12pub 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    // Consume CASE keyword
19    parser.consume(Token::Case)?;
20
21    debug!("Starting CASE expression parsing");
22
23    // Check for simple CASE (CASE expr WHEN value1 THEN ...)
24    // vs searched CASE (CASE WHEN condition1 THEN ...)
25
26    // If the next token is not WHEN, we have a simple CASE
27    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    // Parse WHEN clauses for searched CASE
35    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(); // consume WHEN
43
44        // Parse the condition
45        debug!("Parsing WHEN condition");
46        let condition = parser.parse_expression()?;
47
48        // Expect THEN
49        parser.consume(Token::Then)?;
50
51        // Parse the result expression
52        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    // Check for at least one WHEN clause
64    if when_branches.is_empty() {
65        return Err("CASE expression must have at least one WHEN clause".to_string());
66    }
67
68    // Parse optional ELSE clause
69    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(); // consume ELSE
77        debug!("Parsing ELSE branch");
78        Some(Box::new(parser.parse_expression()?))
79    } else {
80        debug!("No ELSE branch");
81        None
82    };
83
84    // Expect END keyword
85    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
106/// Parse a simple CASE expression
107/// CASE expr WHEN value1 THEN result1 [WHEN value2 THEN result2 ...] [ELSE result] END
108fn 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    // Parse the expression that will be compared
115    debug!("Parsing CASE expression value");
116    let expr = parser.parse_expression()?;
117
118    let mut when_branches = Vec::new();
119
120    // Parse WHEN clauses
121    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(); // consume WHEN
129
130        // Parse the value to compare against
131        debug!("Parsing WHEN value");
132        let value = parser.parse_expression()?;
133
134        // Expect THEN
135        parser.consume(Token::Then)?;
136
137        // Parse the result expression
138        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    // Check for at least one WHEN clause
150    if when_branches.is_empty() {
151        return Err("Simple CASE expression must have at least one WHEN clause".to_string());
152    }
153
154    // Parse optional ELSE clause
155    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(); // consume ELSE
163        debug!("Parsing ELSE branch");
164        Some(Box::new(parser.parse_expression()?))
165    } else {
166        debug!("No ELSE branch");
167        None
168    };
169
170    // Expect END keyword
171    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
193/// Trait that parsers must implement to use CASE expression parsing
194pub trait ParseCase {
195    fn current_token(&self) -> &Token;
196    fn advance(&mut self);
197    fn consume(&mut self, expected: Token) -> Result<(), String>;
198
199    // Parse a general expression (for conditions and results)
200    fn parse_expression(&mut self) -> Result<SqlExpression, String>;
201}