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::{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    // For now, we only support searched CASE
26
27    let mut when_branches = Vec::new();
28
29    // Parse WHEN clauses
30    while matches!(parser.current_token(), Token::When) {
31        log_parse_decision(
32            "parse_case_expression",
33            parser.current_token(),
34            "WHEN clause found, parsing condition and result",
35        );
36
37        parser.advance(); // consume WHEN
38
39        // Parse the condition
40        debug!("Parsing WHEN condition");
41        let condition = parser.parse_expression()?;
42
43        // Expect THEN
44        parser.consume(Token::Then)?;
45
46        // Parse the result expression
47        debug!("Parsing THEN result");
48        let result = parser.parse_expression()?;
49
50        when_branches.push(WhenBranch {
51            condition: Box::new(condition),
52            result: Box::new(result),
53        });
54
55        debug!("Added WHEN branch #{}", when_branches.len());
56    }
57
58    // Check for at least one WHEN clause
59    if when_branches.is_empty() {
60        return Err("CASE expression must have at least one WHEN clause".to_string());
61    }
62
63    // Parse optional ELSE clause
64    let else_branch = if matches!(parser.current_token(), Token::Else) {
65        log_parse_decision(
66            "parse_case_expression",
67            parser.current_token(),
68            "ELSE clause found, parsing default result",
69        );
70
71        parser.advance(); // consume ELSE
72        debug!("Parsing ELSE branch");
73        Some(Box::new(parser.parse_expression()?))
74    } else {
75        debug!("No ELSE branch");
76        None
77    };
78
79    // Expect END keyword
80    parser.consume(Token::End)?;
81
82    debug!(
83        "Completed CASE expression with {} WHEN branches{}",
84        when_branches.len(),
85        if else_branch.is_some() {
86            " and ELSE"
87        } else {
88            ""
89        }
90    );
91
92    let result = Ok(SqlExpression::CaseExpression {
93        when_branches,
94        else_branch,
95    });
96
97    trace_parse_exit("parse_case_expression", &result);
98    result
99}
100
101/// Trait that parsers must implement to use CASE expression parsing
102pub trait ParseCase {
103    fn current_token(&self) -> &Token;
104    fn advance(&mut self);
105    fn consume(&mut self, expected: Token) -> Result<(), String>;
106
107    // Parse a general expression (for conditions and results)
108    fn parse_expression(&mut self) -> Result<SqlExpression, String>;
109}