Skip to main content

radixdb_sql/
expressions.rs

1// Copyright 2026 RadixDB Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Expression parsing methods for the SQL Parser
16
17use radixdb_core::SmartString;
18
19use super::ast::*;
20use super::parser::Parser;
21use super::precedence::Precedence;
22use super::token::{Token, TokenType};
23
24fn validate_cast_type_name(type_name: &str) -> Result<(), String> {
25    let upper = type_name.to_ascii_uppercase();
26    let (base, arguments) = match upper.split_once('(') {
27        Some((base, suffix)) => {
28            let Some(arguments) = suffix.strip_suffix(')') else {
29                return Err(format!("invalid CAST target type: {type_name}"));
30            };
31            (base, Some(arguments))
32        }
33        None => (upper.as_str(), None),
34    };
35
36    // External types are deliberately schema-qualified. Their existence and
37    // identity are catalog concerns resolved by the executor, not parser
38    // keywords maintained beside the catalog.
39    if arguments.is_none()
40        && base.contains('.')
41        && base.split('.').all(|component| !component.is_empty())
42    {
43        return Ok(());
44    }
45
46    if !matches!(
47        base,
48        "INTEGER"
49            | "INT"
50            | "BIGINT"
51            | "SMALLINT"
52            | "TINYINT"
53            | "FLOAT"
54            | "DOUBLE"
55            | "DOUBLE PRECISION"
56            | "REAL"
57            | "DECIMAL"
58            | "NUMERIC"
59            | "TEXT"
60            | "VARCHAR"
61            | "CHAR"
62            | "STRING"
63            | "CLOB"
64            | "BOOLEAN"
65            | "BOOL"
66            | "TIMESTAMP"
67            | "TIMESTAMPTZ"
68            | "TIMESTAMP WITH TIME ZONE"
69            | "TIMESTAMP WITHOUT TIME ZONE"
70            | "DATETIME"
71            | "TIME"
72            | "TIME WITHOUT TIME ZONE"
73            | "DATE"
74            | "JSON"
75            | "JSONB"
76            | "UUID"
77            | "BYTES"
78            | "BLOB"
79            | "BINARY"
80            | "VARBINARY"
81            | "VECTOR"
82    ) {
83        return Err(format!("unknown CAST target type: {type_name}"));
84    }
85
86    let Some(arguments) = arguments else {
87        return Ok(());
88    };
89    let values: Vec<&str> = arguments.split(',').map(str::trim).collect();
90    let parse_positive = |value: &str| value.parse::<usize>().ok().filter(|&parsed| parsed > 0);
91
92    match base {
93        "VARCHAR" | "CHAR" => {
94            if values.len() == 1 && parse_positive(values[0]).is_some() {
95                Ok(())
96            } else {
97                Err(format!("{base} requires one positive length"))
98            }
99        }
100        "DECIMAL" | "NUMERIC" => {
101            let Some(precision) = values.first().and_then(|value| parse_positive(value)) else {
102                return Err(format!("{base} requires a positive precision"));
103            };
104            if values.len() > 2 || precision > 38 {
105                return Err(format!("invalid {base} precision/scale: {arguments}"));
106            }
107            if let Some(scale) = values.get(1).and_then(|value| value.parse::<usize>().ok()) {
108                if scale <= precision {
109                    Ok(())
110                } else {
111                    Err(format!("{base} scale cannot exceed precision"))
112                }
113            } else if values.len() == 1 {
114                Ok(())
115            } else {
116                Err(format!("invalid {base} precision/scale: {arguments}"))
117            }
118        }
119        "VECTOR" => {
120            if values.len() == 1
121                && parse_positive(values[0]).is_some_and(|dimension| dimension <= u16::MAX as usize)
122            {
123                Ok(())
124            } else {
125                Err("VECTOR requires one dimension between 1 and 65535".to_string())
126            }
127        }
128        _ => Err(format!("type modifiers are not supported for {base}")),
129    }
130}
131
132fn window_frame_rank(bound: &WindowFrameBound) -> i128 {
133    match bound {
134        WindowFrameBound::UnboundedPreceding => i128::MIN,
135        WindowFrameBound::Preceding(expression) => match expression.as_ref() {
136            Expression::IntegerLiteral(value) => -(value.value as i128),
137            _ => unreachable!("window offsets are validated before frame ordering"),
138        },
139        WindowFrameBound::CurrentRow => 0,
140        WindowFrameBound::Following(expression) => match expression.as_ref() {
141            Expression::IntegerLiteral(value) => value.value as i128,
142            _ => unreachable!("window offsets are validated before frame ordering"),
143        },
144        WindowFrameBound::UnboundedFollowing => i128::MAX,
145    }
146}
147
148fn window_frame_is_ordered(start: &WindowFrameBound, end: Option<&WindowFrameBound>) -> bool {
149    if matches!(start, WindowFrameBound::UnboundedFollowing)
150        || end.is_some_and(|bound| matches!(bound, WindowFrameBound::UnboundedPreceding))
151    {
152        return false;
153    }
154    window_frame_rank(start)
155        <= end
156            .map(window_frame_rank)
157            .unwrap_or_else(|| window_frame_rank(&WindowFrameBound::CurrentRow))
158}
159
160impl Parser {
161    /// Parse an expression with the given precedence
162    pub fn parse_expression(&mut self, precedence: Precedence) -> Option<Expression> {
163        if !self.enter_expression() {
164            return None;
165        }
166        let result = self.parse_expression_inner(precedence);
167        self.expression_depth -= 1;
168        result
169    }
170
171    fn parse_expression_inner(&mut self, precedence: Precedence) -> Option<Expression> {
172        // Parse prefix expression
173        let mut left = self.parse_prefix_expression()?;
174
175        // Parse infix expressions while precedence allows
176        while !self.peek_token_is(TokenType::Eof) && precedence < self.peek_precedence() {
177            // Check if this is an infix operator we can handle
178            if !self.is_infix_token() {
179                return Some(left);
180            }
181
182            self.next_token();
183            left = self.parse_infix_expression(left)?;
184        }
185
186        Some(left)
187    }
188
189    /// Check if the peek token is an infix operator
190    fn is_infix_token(&self) -> bool {
191        match self.peek_token.token_type {
192            TokenType::Operator => true,
193            TokenType::Keyword => {
194                let kw = self.peek_token.literal.to_uppercase();
195                matches!(
196                    kw.as_str(),
197                    "AND"
198                        | "OR"
199                        | "XOR"
200                        | "LIKE"
201                        | "ILIKE"
202                        | "GLOB"
203                        | "REGEXP"
204                        | "RLIKE"
205                        | "IS"
206                        | "IN"
207                        | "BETWEEN"
208                        | "NOT"
209                )
210            }
211            TokenType::Punctuator => {
212                matches!(self.peek_token.literal.as_str(), "." | "(" | "[")
213            }
214            _ => false,
215        }
216    }
217
218    /// Parse a prefix expression (literals, identifiers, unary operators, etc.)
219    fn parse_prefix_expression(&mut self) -> Option<Expression> {
220        match self.cur_token.token_type {
221            TokenType::Identifier => Some(self.parse_identifier()),
222            TokenType::Integer => self.parse_integer_literal(),
223            TokenType::Float => self.parse_float_literal(),
224            TokenType::String => Some(self.parse_string_literal()),
225            TokenType::Parameter => self.parse_parameter(),
226            TokenType::Keyword => self.parse_keyword_expression(),
227            TokenType::Operator => self.parse_unary_expression(),
228            TokenType::Punctuator => self.parse_punctuator_expression(),
229            TokenType::Error => {
230                // Error token - the literal contains the error message
231                self.add_error(self.cur_token.literal.to_string());
232                None
233            }
234            _ => {
235                if self.cur_token.token_type == TokenType::Eof {
236                    if self.current_clause.is_empty() {
237                        self.add_error("unexpected end of input, expected expression".to_string());
238                    } else {
239                        self.add_error(format!(
240                            "expected expression after {}",
241                            self.current_clause
242                        ));
243                    }
244                } else {
245                    self.add_error(format!(
246                        "unexpected '{}', expected expression",
247                        self.cur_token.literal
248                    ));
249                }
250                None
251            }
252        }
253    }
254
255    /// Parse an identifier
256    fn parse_identifier(&self) -> Expression {
257        // SQL standard: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP are
258        // niladic functions (zero-argument, no parentheses required).
259        // When NOT followed by '(', emit as FunctionCall directly so they
260        // flow through the function evaluation path in all contexts
261        // (SELECT, WHERE, pushdown, etc.). When followed by '(', let the
262        // normal identifier→function-call infix parsing handle it.
263        if !self.cur_token.quoted && !self.peek_token_is_punctuator("(") {
264            let upper = self.cur_token.literal.to_uppercase();
265            if upper == "CURRENT_DATE" || upper == "CURRENT_TIME" || upper == "CURRENT_TIMESTAMP" {
266                return Expression::FunctionCall(Box::new(FunctionCall {
267                    token: self.cur_token.clone(),
268                    function: SmartString::new(&upper),
269                    arguments: vec![],
270                    is_distinct: false,
271                    order_by: vec![],
272                    filter: None,
273                }));
274            }
275        }
276        Expression::Identifier(Identifier::new(
277            self.cur_token.clone(),
278            self.cur_token.literal.clone(),
279        ))
280    }
281
282    /// Parse an integer literal
283    fn parse_integer_literal(&mut self) -> Option<Expression> {
284        match self.cur_token.literal.parse::<i64>() {
285            Ok(value) => Some(Expression::IntegerLiteral(IntegerLiteral {
286                token: self.cur_token.clone(),
287                value,
288            })),
289            Err(error) => {
290                self.add_error(format!(
291                    "integer literal {} is out of range for i64: {}",
292                    self.cur_token.literal, error
293                ));
294                None
295            }
296        }
297    }
298
299    /// Parse a float literal
300    fn parse_float_literal(&mut self) -> Option<Expression> {
301        self.parse_finite_float_value().map(|value| {
302            Expression::FloatLiteral(FloatLiteral {
303                token: self.cur_token.clone(),
304                value,
305            })
306        })
307    }
308
309    /// Parse a finite f64 without silently inventing infinity or zero.
310    fn parse_finite_float_value(&mut self) -> Option<f64> {
311        let source = self.cur_token.literal.as_str();
312        match source.parse::<f64>() {
313            Ok(value) if !value.is_finite() => {
314                self.add_error(format!(
315                    "float literal {} is out of finite f64 range",
316                    source
317                ));
318                None
319            }
320            Ok(value)
321                if value == 0.0
322                    && source.split(['e', 'E']).next().is_some_and(|mantissa| {
323                        mantissa.bytes().any(|b| matches!(b, b'1'..=b'9'))
324                    }) =>
325            {
326                self.add_error(format!("float literal {} underflows finite f64", source));
327                None
328            }
329            Ok(value) => Some(value),
330            Err(e) => {
331                self.add_error(format!("could not parse {} as float: {}", source, e));
332                None
333            }
334        }
335    }
336
337    /// Parse a string literal
338    fn parse_string_literal(&self) -> Expression {
339        let literal = &self.cur_token.literal;
340        // Remove surrounding quotes
341        let value = if literal.len() >= 2 {
342            let inner = &literal[1..literal.len() - 1];
343            // Handle escape sequences - optimized to avoid allocations when no escapes present
344            // Note: We don't convert \" to " because:
345            // 1. In SQL, double quotes don't need escaping inside single-quoted strings
346            // 2. Converting \" to " breaks JSON content like {"key":"value with \"quotes\""}
347            if inner.contains('\\') {
348                // Has escapes - do single-pass replacement
349                let mut result = String::with_capacity(inner.len());
350                let mut chars = inner.chars().peekable();
351                while let Some(c) = chars.next() {
352                    if c == '\\' {
353                        match chars.peek() {
354                            Some('n') => {
355                                result.push('\n');
356                                chars.next();
357                            }
358                            Some('t') => {
359                                result.push('\t');
360                                chars.next();
361                            }
362                            Some('r') => {
363                                result.push('\r');
364                                chars.next();
365                            }
366                            Some('\'') => {
367                                result.push('\'');
368                                chars.next();
369                            }
370                            Some('\\') => {
371                                result.push('\\');
372                                chars.next();
373                            }
374                            _ => result.push(c), // Keep backslash for unknown escapes
375                        }
376                    } else {
377                        result.push(c);
378                    }
379                }
380                SmartString::from_string(result)
381            } else {
382                // No escapes - zero allocation path
383                SmartString::new(inner)
384            }
385        } else {
386            literal.clone()
387        };
388
389        Expression::StringLiteral(StringLiteral {
390            token: self.cur_token.clone(),
391            value,
392            type_hint: None,
393        })
394    }
395
396    /// Parse a parameter ($1, ?, :name)
397    fn parse_parameter(&mut self) -> Option<Expression> {
398        let name = self.cur_token.literal.clone();
399        let index = if name == "?" {
400            if self.positional_parameter_style
401                == Some(super::parser::PositionalParameterStyle::Explicit)
402            {
403                self.add_error("cannot mix '?' and '$n' positional parameters".to_string());
404                return None;
405            }
406            self.positional_parameter_style =
407                Some(super::parser::PositionalParameterStyle::Anonymous);
408            self.next_parameter_index()
409        } else if let Some(stripped) = name.strip_prefix('$') {
410            if self.positional_parameter_style
411                == Some(super::parser::PositionalParameterStyle::Anonymous)
412            {
413                self.add_error("cannot mix '?' and '$n' positional parameters".to_string());
414                return None;
415            }
416            self.positional_parameter_style =
417                Some(super::parser::PositionalParameterStyle::Explicit);
418            match stripped.parse::<usize>() {
419                Ok(0) => {
420                    self.add_error(
421                        "positional parameter indexes start at $1; $0 is invalid".to_string(),
422                    );
423                    return None;
424                }
425                Ok(idx) => idx,
426                Err(e) => {
427                    self.add_error(format!("invalid parameter index: {}", e));
428                    return None;
429                }
430            }
431        } else if name.starts_with(':') {
432            // Named parameter - use 0 as index, will be resolved by name
433            0
434        } else {
435            self.add_error(format!("invalid parameter format: {}", name));
436            return None;
437        };
438
439        Some(Expression::Parameter(Parameter {
440            token: self.cur_token.clone(),
441            name,
442            index,
443            field: None,
444        }))
445    }
446
447    /// Parse a keyword expression (TRUE, FALSE, NULL, CASE, CAST, etc.)
448    fn parse_keyword_expression(&mut self) -> Option<Expression> {
449        let keyword = self.cur_token.literal.to_uppercase();
450        match keyword.as_str() {
451            "TRUE" => Some(Expression::BooleanLiteral(BooleanLiteral {
452                token: self.cur_token.clone(),
453                value: true,
454            })),
455            "FALSE" => Some(Expression::BooleanLiteral(BooleanLiteral {
456                token: self.cur_token.clone(),
457                value: false,
458            })),
459            "NULL" => Some(Expression::NullLiteral(NullLiteral {
460                token: self.cur_token.clone(),
461            })),
462            "CASE" => self.parse_case_expression(),
463            "CAST" => self.parse_cast_expression(),
464            "EXTRACT" => self.parse_extract_expression(),
465            "EXISTS" => self.parse_exists_expression(),
466            "NOT" => self.parse_not_expression(),
467            "INTERVAL" => self.parse_interval_literal(),
468            "DEFAULT" => Some(Expression::Default(DefaultExpression {
469                token: self.cur_token.clone(),
470            })),
471            "TIMESTAMP" | "TIMESTAMPTZ" | "DATE" | "TIME" => {
472                // These can be either typed literals (TIMESTAMP 'value') or column names
473                if self.peek_token_is(TokenType::String) {
474                    self.parse_typed_literal()
475                } else {
476                    // Treat as identifier (column name)
477                    Some(Expression::Identifier(Identifier::new(
478                        self.cur_token.clone(),
479                        self.cur_token.literal.clone(),
480                    )))
481                }
482            }
483            // Keywords that can also be function names when followed by (
484            "LEFT" | "RIGHT" | "CHAR" | "FIRST" | "LAST" | "TRUNCATE" => {
485                if self.peek_token_is_punctuator("(") {
486                    // Treat as function call
487                    let ident = Expression::Identifier(Identifier::new(
488                        self.cur_token.clone(),
489                        self.cur_token.literal.clone(),
490                    ));
491                    self.next_token(); // move to (
492                    self.parse_function_call(ident)
493                } else {
494                    // Treat as identifier if not followed by (
495                    Some(Expression::Identifier(Identifier::new(
496                        self.cur_token.clone(),
497                        self.cur_token.literal.clone(),
498                    )))
499                }
500            }
501            // Non-reserved keywords can be used as column names
502            _ if !Self::is_reserved_keyword(&keyword) => Some(Expression::Identifier(
503                Identifier::new(self.cur_token.clone(), self.cur_token.literal.clone()),
504            )),
505            _ => {
506                if self.current_clause.is_empty() {
507                    self.add_error(format!(
508                        "'{}' cannot be used here, expected expression",
509                        keyword
510                    ));
511                } else {
512                    self.add_error(format!(
513                        "'{}' cannot be used in {} clause, expected expression",
514                        keyword, self.current_clause
515                    ));
516                }
517                None
518            }
519        }
520    }
521
522    /// Parse a unary/prefix operator expression
523    fn parse_unary_expression(&mut self) -> Option<Expression> {
524        let token = self.cur_token.clone();
525        let operator = self.cur_token.literal.clone();
526
527        // Special case: * as standalone (for SELECT *, RETURNING *, etc.)
528        // When * appears as a prefix and the next token is not something that
529        // could continue a multiplication, treat it as Star expression
530        if operator == "*" {
531            // Check if this is standalone * (not multiplication)
532            // Peek at next token to see if it could be a multiplication operand
533            if self.peek_token.is_eof()
534                || self.peek_token.is_punctuator(",")
535                || self.peek_token.is_punctuator(";")
536                || self.peek_token.is_punctuator(")")
537                || self.peek_token_is_keyword("FROM")
538                || self.peek_token_is_keyword("WHERE")
539                || self.peek_token_is_keyword("ORDER")
540                || self.peek_token_is_keyword("GROUP")
541                || self.peek_token_is_keyword("HAVING")
542                || self.peek_token_is_keyword("LIMIT")
543                || self.peek_token_is_keyword("UNION")
544                || self.peek_token_is_keyword("INTERSECT")
545                || self.peek_token_is_keyword("EXCEPT")
546            {
547                return Some(Expression::Star(StarExpression { token }));
548            }
549        }
550
551        self.next_token();
552
553        // Special case: negative numbers
554        if operator == "-"
555            && (self.cur_token_is(TokenType::Integer) || self.cur_token_is(TokenType::Float))
556        {
557            if self.cur_token_is(TokenType::Integer) {
558                // Handle i64::MIN special case: -9223372036854775808
559                // The literal "9223372036854775808" is too large for i64, but when negated
560                // it equals i64::MIN. We must check this before trying parse::<i64>().
561                if self.cur_token.literal == "9223372036854775808" {
562                    return Some(Expression::IntegerLiteral(IntegerLiteral {
563                        token: self.cur_token.clone(),
564                        value: i64::MIN,
565                    }));
566                }
567                if let Ok(value) = self.cur_token.literal.parse::<i64>() {
568                    return Some(Expression::IntegerLiteral(IntegerLiteral {
569                        token: self.cur_token.clone(),
570                        value: -value,
571                    }));
572                }
573            } else {
574                let value = self.parse_finite_float_value()?;
575                return Some(Expression::FloatLiteral(FloatLiteral {
576                    token: self.cur_token.clone(),
577                    value: -value,
578                }));
579            }
580        }
581
582        let right = self.parse_expression(Precedence::Prefix)?;
583
584        Some(Expression::Prefix(PrefixExpression::new(
585            token,
586            operator,
587            Box::new(right),
588        )))
589    }
590
591    /// Parse a punctuator expression (parentheses, star)
592    fn parse_punctuator_expression(&mut self) -> Option<Expression> {
593        match self.cur_token.literal.as_str() {
594            "(" => self.parse_grouped_expression(),
595            "*" => Some(Expression::Star(StarExpression {
596                token: self.cur_token.clone(),
597            })),
598            _ => {
599                self.add_error(format!(
600                    "unexpected punctuator: {} at {}",
601                    self.cur_token.literal, self.cur_token.position
602                ));
603                None
604            }
605        }
606    }
607
608    /// Parse a grouped expression, tuple, or scalar subquery
609    fn parse_grouped_expression(&mut self) -> Option<Expression> {
610        let token = self.cur_token.clone();
611
612        // Check for subquery
613        if self.peek_token_is_keyword("SELECT") {
614            self.next_token(); // Move to SELECT
615            let subquery = self.parse_select_statement()?;
616
617            if !self.peek_token_is_punctuator(")") {
618                self.add_error(format!(
619                    "expected ')' after scalar subquery, got {}",
620                    Self::format_token_for_error(&self.peek_token)
621                ));
622                return None;
623            }
624            self.next_token();
625
626            return Some(Expression::ScalarSubquery(ScalarSubquery {
627                token,
628                subquery: Box::new(subquery),
629            }));
630        }
631
632        self.next_token(); // Move past (
633
634        // Empty parentheses
635        if self.cur_token_is_punctuator(")") {
636            return Some(Expression::Identifier(Identifier::new(
637                self.cur_token.clone(),
638                SmartString::const_new("()"),
639            )));
640        }
641
642        let first_expr = self.parse_expression(Precedence::Lowest)?;
643
644        // Check if this is a tuple (comma-separated list)
645        if self.peek_token_is_punctuator(",") {
646            let mut expressions = vec![first_expr];
647
648            while self.peek_token_is_punctuator(",") {
649                self.next_token(); // consume comma
650                self.next_token(); // move to next expression
651
652                if let Some(expr) = self.parse_expression(Precedence::Lowest) {
653                    expressions.push(expr);
654                }
655            }
656
657            if !self.peek_token_is_punctuator(")") {
658                self.add_error(format!(
659                    "expected ')', got {}",
660                    Self::format_token_for_error(&self.peek_token)
661                ));
662                return None;
663            }
664            self.next_token();
665
666            // Return as ExpressionList (tuple)
667            return Some(Expression::ExpressionList(Box::new(ExpressionList {
668                token,
669                expressions,
670            })));
671        }
672
673        if !self.peek_token_is_punctuator(")") {
674            self.add_error(format!(
675                "expected ')', got {}",
676                Self::format_token_for_error(&self.peek_token)
677            ));
678            return None;
679        }
680        self.next_token();
681
682        Some(first_expr)
683    }
684
685    /// Parse an infix expression
686    fn parse_infix_expression(&mut self, left: Expression) -> Option<Expression> {
687        match self.cur_token.token_type {
688            TokenType::Operator => self.parse_binary_expression(left),
689            TokenType::Keyword => self.parse_keyword_infix(left),
690            TokenType::Punctuator => self.parse_punctuator_infix(left),
691            _ => {
692                self.add_error(format!(
693                    "unexpected infix token: {:?} at {}",
694                    self.cur_token.token_type, self.cur_token.position
695                ));
696                None
697            }
698        }
699    }
700
701    /// Parse a binary operator expression
702    fn parse_binary_expression(&mut self, left: Expression) -> Option<Expression> {
703        let token = self.cur_token.clone();
704        let operator = self.cur_token.literal.clone();
705        let precedence = self.cur_precedence();
706
707        self.next_token();
708
709        // Check for ALL/ANY/SOME subquery comparison
710        if self.cur_token_is_keyword("ALL")
711            || self.cur_token_is_keyword("ANY")
712            || self.cur_token_is_keyword("SOME")
713        {
714            if !matches!(
715                operator.as_str(),
716                "=" | "<>" | "!=" | "<" | "<=" | ">" | ">="
717            ) {
718                self.add_error(format!(
719                    "{} is not a valid comparison operator before {}",
720                    operator, self.cur_token.literal
721                ));
722                return None;
723            }
724            return self.parse_all_any_expression(left, token, operator);
725        }
726
727        let right = self.parse_expression(precedence)?;
728
729        Some(Expression::Infix(InfixExpression::new(
730            token,
731            Box::new(left),
732            operator,
733            Box::new(right),
734        )))
735    }
736
737    /// Parse ALL/ANY/SOME subquery comparison (e.g., x > ALL (SELECT ...))
738    fn parse_all_any_expression(
739        &mut self,
740        left: Expression,
741        token: Token,
742        operator: SmartString,
743    ) -> Option<Expression> {
744        use super::ast::{AllAnyExpression, AllAnyType};
745
746        let all_any_type = if self.cur_token_is_keyword("ALL") {
747            AllAnyType::All
748        } else {
749            AllAnyType::Any // SOME is an alias for ANY
750        };
751
752        // Move past ALL/ANY/SOME
753        self.next_token();
754
755        // Expect opening parenthesis
756        if !self.cur_token_is_punctuator("(") {
757            self.add_error(format!(
758                "expected '(' after {} at {}",
759                all_any_type, self.cur_token.position
760            ));
761            return None;
762        }
763
764        // Move past (
765        self.next_token();
766
767        // Parse subquery
768        if !self.cur_token_is_keyword("SELECT") {
769            self.add_error(format!(
770                "expected SELECT in {} subquery at {}",
771                all_any_type, self.cur_token.position
772            ));
773            return None;
774        }
775
776        let subquery = self.parse_select_statement()?;
777
778        // Expect closing parenthesis
779        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
780            self.add_error(format!(
781                "expected ')' after {} subquery at {}",
782                all_any_type, self.cur_token.position
783            ));
784            return None;
785        }
786
787        Some(Expression::AllAny(AllAnyExpression {
788            token,
789            left: Box::new(left),
790            operator,
791            all_any_type,
792            subquery: Box::new(subquery),
793        }))
794    }
795
796    /// Parse a keyword infix expression (AND, OR, LIKE, IS, IN, BETWEEN)
797    fn parse_keyword_infix(&mut self, left: Expression) -> Option<Expression> {
798        let keyword = self.cur_token.literal.to_uppercase();
799        match keyword.as_str() {
800            "AND" | "OR" | "XOR" => {
801                let token = self.cur_token.clone();
802                let operator = keyword.clone();
803                let precedence = self.cur_precedence();
804
805                self.next_token();
806                let right = self.parse_expression(precedence)?;
807
808                Some(Expression::Infix(InfixExpression::new(
809                    token,
810                    Box::new(left),
811                    operator,
812                    Box::new(right),
813                )))
814            }
815            "LIKE" | "ILIKE" | "GLOB" | "REGEXP" | "RLIKE" => {
816                self.parse_like_expression(left, keyword.clone(), false)
817            }
818            "IS" => self.parse_is_expression(left),
819            "IN" => self.parse_in_expression(left, false),
820            "BETWEEN" => self.parse_between_expression(left, false),
821            "NOT" => {
822                // Handle NOT IN, NOT BETWEEN, NOT LIKE, NOT ILIKE, NOT GLOB, NOT REGEXP, NOT RLIKE
823                if self.peek_token_is_keyword("IN") {
824                    self.next_token(); // consume IN
825                    self.parse_in_expression(left, true)
826                } else if self.peek_token_is_keyword("BETWEEN") {
827                    self.next_token(); // consume BETWEEN
828                    self.parse_between_expression(left, true)
829                } else if self.peek_token_is_keyword("LIKE") {
830                    self.next_token(); // consume LIKE
831                    self.parse_like_expression(left, SmartString::const_new("LIKE"), true)
832                } else if self.peek_token_is_keyword("ILIKE") {
833                    self.next_token(); // consume ILIKE
834                    self.parse_like_expression(left, SmartString::const_new("ILIKE"), true)
835                } else if self.peek_token_is_keyword("GLOB") {
836                    self.next_token(); // consume GLOB
837                    self.parse_like_expression(left, SmartString::const_new("GLOB"), true)
838                } else if self.peek_token_is_keyword("REGEXP") {
839                    self.next_token(); // consume REGEXP
840                    self.parse_like_expression(left, SmartString::const_new("REGEXP"), true)
841                } else if self.peek_token_is_keyword("RLIKE") {
842                    self.next_token(); // consume RLIKE
843                    self.parse_like_expression(left, SmartString::const_new("RLIKE"), true)
844                } else {
845                    self.add_error(format!(
846                        "NOT must be followed by IN, BETWEEN, LIKE, ILIKE, GLOB, REGEXP, or RLIKE at {}",
847                        self.peek_token.position
848                    ));
849                    None
850                }
851            }
852            _ => {
853                self.add_error(format!(
854                    "unexpected infix keyword: {} at {}",
855                    keyword, self.cur_token.position
856                ));
857                None
858            }
859        }
860    }
861
862    /// Parse a punctuator infix expression (., (, [)
863    fn parse_punctuator_infix(&mut self, left: Expression) -> Option<Expression> {
864        match self.cur_token.literal.as_str() {
865            "." => self.parse_qualified_identifier(left),
866            "(" => self.parse_function_call(left),
867            "[" => self.parse_index_expression(left),
868            "*" => {
869                // Multiplication
870                let token = self.cur_token.clone();
871                let precedence = Precedence::Product;
872
873                self.next_token();
874                let right = self.parse_expression(precedence)?;
875
876                Some(Expression::Infix(InfixExpression::new(
877                    token,
878                    Box::new(left),
879                    SmartString::const_new("*"),
880                    Box::new(right),
881                )))
882            }
883            _ => {
884                self.add_error(format!(
885                    "unexpected infix punctuator: {} at {}",
886                    self.cur_token.literal, self.cur_token.position
887                ));
888                None
889            }
890        }
891    }
892
893    /// Parse a qualified identifier, unresolved multi-part path, or qualified
894    /// star. Schema meaning is intentionally not assigned by the parser.
895    fn parse_qualified_identifier(&mut self, left: Expression) -> Option<Expression> {
896        if let Expression::Parameter(mut parameter) = left {
897            if parameter.index != 0 || !parameter.name.starts_with(':') || parameter.field.is_some()
898            {
899                self.add_error(format!(
900                    "only one field may follow a named parameter at {}",
901                    self.cur_token.position
902                ));
903                return None;
904            }
905            if !self.peek_token_is(TokenType::Identifier) && !self.peek_token_is(TokenType::Keyword)
906            {
907                self.peek_error(TokenType::Identifier);
908                return None;
909            }
910            self.next_token();
911            parameter.field = Some(Box::new(Identifier::new(
912                self.cur_token.clone(),
913                self.cur_token.literal.clone(),
914            )));
915            return Some(Expression::Parameter(parameter));
916        }
917        let mut qualified = match left {
918            Expression::Identifier(id) => QualifiedIdentifier {
919                token: id.token.clone(),
920                qualifier: Box::new(id),
921                intermediate: None,
922                name: Box::new(Identifier::new(
923                    self.cur_token.clone(),
924                    SmartString::const_new(""),
925                )),
926            },
927            Expression::QualifiedIdentifier(path) => path,
928            _ => {
929                self.add_error(format!(
930                    "left side of '.' must be an identifier path at {}",
931                    self.cur_token.position
932                ));
933                return None;
934            }
935        };
936
937        // Check for qualified star (table.*)
938        if self.peek_token_is_operator("*") {
939            if qualified.is_multi_part_path() || !qualified.name.value.is_empty() {
940                self.add_error(format!(
941                    "qualified star cannot follow a multi-part identifier path at {}",
942                    self.cur_token.position
943                ));
944                return None;
945            }
946            self.next_token(); // consume *
947            return Some(Expression::QualifiedStar(QualifiedStarExpression {
948                token: qualified.qualifier.token.clone(),
949                qualifier: qualified.qualifier.value,
950            }));
951        }
952
953        // Allow both identifiers and keywords as column names (e.g., t.level, t.type)
954        // Keywords like LEVEL can be valid column names when used after a dot
955        if !self.peek_token_is(TokenType::Identifier) && !self.peek_token_is(TokenType::Keyword) {
956            self.peek_error(TokenType::Identifier);
957            return None;
958        }
959        self.next_token();
960        let next = Identifier::new(self.cur_token.clone(), self.cur_token.literal.clone());
961        if !qualified.name.value.is_empty() {
962            qualified
963                .intermediate
964                .get_or_insert_with(|| Box::new(Vec::new()))
965                .push(*qualified.name);
966        }
967        qualified.name = Box::new(next);
968
969        Some(Expression::QualifiedIdentifier(qualified))
970    }
971
972    /// Parse a function call
973    fn parse_function_call(&mut self, left: Expression) -> Option<Expression> {
974        let left_ident = match left {
975            Expression::Identifier(id) => id,
976            _ => {
977                self.add_error(format!(
978                    "left side of '(' must be an identifier at {}",
979                    self.cur_token.position
980                ));
981                return None;
982            }
983        };
984
985        let mut call = FunctionCall {
986            token: left_ident.token.clone(),
987            function: left_ident.value.to_uppercase(),
988            arguments: Vec::new(),
989            is_distinct: false,
990            order_by: Vec::new(),
991            filter: None,
992        };
993
994        // Check for empty function call
995        if self.peek_token_is_punctuator(")") {
996            self.next_token();
997            // Check for FILTER clause
998            if self.peek_token_is_keyword("FILTER") {
999                call.filter = self.parse_filter_clause();
1000            }
1001            // Check for OVER clause (window function with no arguments)
1002            if self.peek_token_is_keyword("OVER") {
1003                return self.parse_window_expression(call);
1004            }
1005            return Some(Expression::FunctionCall(Box::new(call)));
1006        }
1007
1008        // Check for * argument (COUNT(*))
1009        if self.peek_token_is_operator("*") {
1010            self.next_token();
1011            call.arguments.push(Expression::Star(StarExpression {
1012                token: self.cur_token.clone(),
1013            }));
1014
1015            // Check for ORDER BY inside function
1016            if self.peek_token_is_keyword("ORDER") {
1017                self.parse_function_order_by(&mut call);
1018            }
1019
1020            if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1021                self.add_error(format!("expected ')' at {}", self.cur_token.position));
1022                return None;
1023            }
1024
1025            // Check for FILTER clause
1026            if self.peek_token_is_keyword("FILTER") {
1027                call.filter = self.parse_filter_clause();
1028            }
1029
1030            // Check for OVER clause (window function with * argument)
1031            if self.peek_token_is_keyword("OVER") {
1032                return self.parse_window_expression(call);
1033            }
1034
1035            return Some(Expression::FunctionCall(Box::new(call)));
1036        }
1037
1038        // Check for DISTINCT
1039        if self.peek_token_is_keyword("DISTINCT") {
1040            self.next_token();
1041            call.is_distinct = true;
1042        }
1043
1044        self.next_token();
1045
1046        // For POSITION(x IN y) syntax, parse first argument with higher precedence
1047        // to prevent IN from being consumed as an infix operator
1048        let first_arg_precedence = if call.function == "POSITION" {
1049            Precedence::LessGreater // Higher than Equals, so IN won't be consumed
1050        } else {
1051            Precedence::Lowest
1052        };
1053
1054        // Parse first argument
1055        if let Some(arg) = self.parse_expression(first_arg_precedence) {
1056            call.arguments.push(arg);
1057        }
1058
1059        // Special handling for POSITION(substring IN string) syntax
1060        // SQL standard: POSITION(substring IN string) returns position of substring in string
1061        if call.function == "POSITION" && self.peek_token_is_keyword("IN") {
1062            self.next_token(); // consume IN
1063            self.next_token(); // move to string expression
1064
1065            if let Some(string_arg) = self.parse_expression(Precedence::Lowest) {
1066                // For POSITION(x IN y), the result is POSITION(x, y) = position of x in y
1067                call.arguments.push(string_arg);
1068            } else {
1069                self.add_error(format!(
1070                    "expected expression after IN in POSITION at {}",
1071                    self.cur_token.position
1072                ));
1073                return None;
1074            }
1075        }
1076
1077        // Parse additional arguments
1078        while self.peek_token_is_punctuator(",") {
1079            self.next_token(); // consume comma
1080            self.next_token(); // move to next arg
1081
1082            if let Some(arg) = self.parse_expression(Precedence::Lowest) {
1083                call.arguments.push(arg);
1084            } else {
1085                self.add_error(format!(
1086                    "expected expression after ',' at {}",
1087                    self.cur_token.position
1088                ));
1089                return None;
1090            }
1091        }
1092
1093        // Check for ORDER BY inside function
1094        if self.peek_token_is_keyword("ORDER") {
1095            self.parse_function_order_by(&mut call);
1096        }
1097
1098        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1099            self.add_error(format!("expected ')' at {}", self.cur_token.position));
1100            return None;
1101        }
1102
1103        // Check for FILTER clause
1104        if self.peek_token_is_keyword("FILTER") {
1105            call.filter = self.parse_filter_clause();
1106        }
1107
1108        // Check for OVER clause (window function)
1109        if self.peek_token_is_keyword("OVER") {
1110            return self.parse_window_expression(call);
1111        }
1112
1113        Some(Expression::FunctionCall(Box::new(call)))
1114    }
1115
1116    /// Parse FILTER clause for aggregate functions (FILTER (WHERE condition))
1117    fn parse_filter_clause(&mut self) -> Option<Box<Expression>> {
1118        self.next_token(); // consume FILTER
1119
1120        // Expect opening parenthesis
1121        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
1122            self.add_error(format!(
1123                "expected '(' after FILTER at {}",
1124                self.cur_token.position
1125            ));
1126            return None;
1127        }
1128
1129        // Expect WHERE keyword
1130        if !self.expect_keyword("WHERE") {
1131            self.add_error(format!(
1132                "expected WHERE after FILTER( at {}",
1133                self.cur_token.position
1134            ));
1135            return None;
1136        }
1137
1138        // Parse the condition
1139        self.next_token();
1140        let condition = self.parse_expression(Precedence::Lowest)?;
1141
1142        // Expect closing parenthesis
1143        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1144            self.add_error(format!(
1145                "expected ')' after FILTER condition at {}",
1146                self.cur_token.position
1147            ));
1148            return None;
1149        }
1150
1151        Some(Box::new(condition))
1152    }
1153
1154    /// Parse ORDER BY inside a function call
1155    fn parse_function_order_by(&mut self, call: &mut FunctionCall) {
1156        self.next_token(); // consume ORDER
1157
1158        if !self.expect_keyword("BY") {
1159            return;
1160        }
1161
1162        self.next_token(); // move to first expression
1163
1164        if let Some(order_expr) = self.parse_order_by_expression() {
1165            call.order_by.push(order_expr);
1166        }
1167
1168        while self.peek_token_is_punctuator(",") {
1169            self.next_token(); // consume comma
1170            self.next_token(); // move to next expression
1171
1172            if let Some(order_expr) = self.parse_order_by_expression() {
1173                call.order_by.push(order_expr);
1174            }
1175        }
1176    }
1177
1178    /// Parse a window expression (function OVER (...) or function OVER window_name)
1179    fn parse_window_expression(&mut self, function: FunctionCall) -> Option<Expression> {
1180        self.next_token(); // consume OVER
1181        let token = self.cur_token.clone();
1182
1183        // Check if this is a named window reference (OVER w) instead of inline spec (OVER (...))
1184        if matches!(
1185            self.peek_token.token_type,
1186            TokenType::Identifier | TokenType::Keyword
1187        ) {
1188            self.next_token(); // consume window name
1189            let window_ref = self.cur_token.literal.clone();
1190            return Some(Expression::Window(Box::new(WindowExpression {
1191                token,
1192                function: Box::new(function),
1193                window_ref: Some(window_ref),
1194                partition_by: Vec::new(),
1195                order_by: Vec::new(),
1196                frame: None,
1197            })));
1198        }
1199
1200        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
1201            self.add_error(format!(
1202                "expected '(' or window name after OVER at {}",
1203                self.cur_token.position
1204            ));
1205            return None;
1206        }
1207
1208        let mut partition_by = Vec::new();
1209        let mut order_by = Vec::new();
1210        let mut frame = None;
1211
1212        // Parse PARTITION BY
1213        if self.peek_token_is_keyword("PARTITION") {
1214            self.next_token(); // consume PARTITION
1215            if !self.expect_keyword("BY") {
1216                return None;
1217            }
1218
1219            self.next_token();
1220            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
1221                partition_by.push(expr);
1222            }
1223
1224            while self.peek_token_is_punctuator(",") {
1225                self.next_token(); // consume comma
1226                self.next_token();
1227                if let Some(expr) = self.parse_expression(Precedence::Lowest) {
1228                    partition_by.push(expr);
1229                }
1230            }
1231        }
1232
1233        // Parse ORDER BY
1234        if self.peek_token_is_keyword("ORDER") {
1235            self.next_token(); // consume ORDER
1236            if !self.expect_keyword("BY") {
1237                return None;
1238            }
1239
1240            self.next_token();
1241            if let Some(order_expr) = self.parse_order_by_expression() {
1242                order_by.push(order_expr);
1243            }
1244
1245            while self.peek_token_is_punctuator(",") {
1246                self.next_token(); // consume comma
1247                self.next_token();
1248                if let Some(order_expr) = self.parse_order_by_expression() {
1249                    order_by.push(order_expr);
1250                }
1251            }
1252        }
1253
1254        // Parse window frame (ROWS/RANGE)
1255        if self.peek_token_is_keyword("ROWS") || self.peek_token_is_keyword("RANGE") {
1256            frame = self.parse_window_frame();
1257        }
1258
1259        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1260            self.add_error(format!(
1261                "expected ')' after window specification at {}",
1262                self.cur_token.position
1263            ));
1264            return None;
1265        }
1266
1267        Some(Expression::Window(Box::new(WindowExpression {
1268            token,
1269            function: Box::new(function),
1270            window_ref: None,
1271            partition_by,
1272            order_by,
1273            frame,
1274        })))
1275    }
1276
1277    /// Parse a window frame (ROWS/RANGE BETWEEN ... AND ...)
1278    fn parse_window_frame(&mut self) -> Option<WindowFrame> {
1279        self.next_token();
1280        let unit = if self.cur_token_is_keyword("ROWS") {
1281            WindowFrameUnit::Rows
1282        } else {
1283            WindowFrameUnit::Range
1284        };
1285
1286        self.next_token();
1287
1288        // Check for BETWEEN
1289        let (start, end) = if self.cur_token_is_keyword("BETWEEN") {
1290            self.next_token();
1291            let start = self.parse_window_frame_bound()?;
1292
1293            if !self.expect_keyword("AND") {
1294                return None;
1295            }
1296            self.next_token();
1297            let end = self.parse_window_frame_bound()?;
1298
1299            (start, Some(end))
1300        } else {
1301            let start = self.parse_window_frame_bound()?;
1302            (start, None)
1303        };
1304
1305        if !window_frame_is_ordered(&start, end.as_ref()) {
1306            self.add_error("window frame start must not follow its end".to_string());
1307            return None;
1308        }
1309
1310        Some(WindowFrame { unit, start, end })
1311    }
1312
1313    /// Parse a window frame bound
1314    fn parse_window_frame_bound(&mut self) -> Option<WindowFrameBound> {
1315        if self.cur_token_is_keyword("CURRENT") {
1316            if !self.expect_keyword("ROW") {
1317                return None;
1318            }
1319            Some(WindowFrameBound::CurrentRow)
1320        } else if self.cur_token_is_keyword("UNBOUNDED") {
1321            self.next_token();
1322            if self.cur_token_is_keyword("PRECEDING") {
1323                Some(WindowFrameBound::UnboundedPreceding)
1324            } else if self.cur_token_is_keyword("FOLLOWING") {
1325                Some(WindowFrameBound::UnboundedFollowing)
1326            } else {
1327                self.add_error(format!(
1328                    "expected PRECEDING or FOLLOWING after UNBOUNDED at {}",
1329                    self.cur_token.position
1330                ));
1331                None
1332            }
1333        } else {
1334            // N PRECEDING or N FOLLOWING
1335            let expr = self.parse_expression(Precedence::Lowest)?;
1336            if !matches!(&expr, Expression::IntegerLiteral(value) if value.value >= 0) {
1337                self.add_error(
1338                    "window frame offset must be a non-negative integer literal".to_string(),
1339                );
1340                return None;
1341            }
1342            self.next_token();
1343            if self.cur_token_is_keyword("PRECEDING") {
1344                Some(WindowFrameBound::Preceding(Box::new(expr)))
1345            } else if self.cur_token_is_keyword("FOLLOWING") {
1346                Some(WindowFrameBound::Following(Box::new(expr)))
1347            } else {
1348                self.add_error(format!(
1349                    "expected PRECEDING or FOLLOWING at {}",
1350                    self.cur_token.position
1351                ));
1352                None
1353            }
1354        }
1355    }
1356
1357    /// Parse an index expression (arr[idx])
1358    fn parse_index_expression(&mut self, left: Expression) -> Option<Expression> {
1359        let token = self.cur_token.clone();
1360
1361        self.next_token();
1362        let index = self.parse_expression(Precedence::Lowest)?;
1363
1364        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "]" {
1365            self.add_error(format!("expected ']' at {}", self.cur_token.position));
1366            return None;
1367        }
1368
1369        Some(Expression::Infix(InfixExpression::new(
1370            token,
1371            Box::new(left),
1372            "[]".to_string(),
1373            Box::new(index),
1374        )))
1375    }
1376
1377    /// Parse an IS expression (IS NULL, IS NOT NULL, IS TRUE, IS FALSE, IS DISTINCT FROM, IS NOT DISTINCT FROM)
1378    fn parse_is_expression(&mut self, left: Expression) -> Option<Expression> {
1379        let token = self.cur_token.clone();
1380        let mut operator = "IS".to_string();
1381
1382        // Check for IS NOT
1383        if self.peek_token_is_keyword("NOT") {
1384            self.next_token();
1385            operator = "IS NOT".to_string();
1386        }
1387
1388        self.next_token();
1389
1390        // Handle IS NULL / IS NOT NULL
1391        if self.cur_token_is_keyword("NULL") {
1392            return Some(Expression::Infix(InfixExpression::new(
1393                token,
1394                Box::new(left),
1395                operator,
1396                Box::new(Expression::NullLiteral(NullLiteral {
1397                    token: self.cur_token.clone(),
1398                })),
1399            )));
1400        }
1401
1402        // Handle IS TRUE / IS NOT TRUE
1403        if self.cur_token_is_keyword("TRUE") {
1404            return Some(Expression::Infix(InfixExpression::new(
1405                token,
1406                Box::new(left),
1407                operator,
1408                Box::new(Expression::BooleanLiteral(BooleanLiteral {
1409                    token: self.cur_token.clone(),
1410                    value: true,
1411                })),
1412            )));
1413        }
1414
1415        // Handle IS FALSE / IS NOT FALSE
1416        if self.cur_token_is_keyword("FALSE") {
1417            return Some(Expression::Infix(InfixExpression::new(
1418                token,
1419                Box::new(left),
1420                operator,
1421                Box::new(Expression::BooleanLiteral(BooleanLiteral {
1422                    token: self.cur_token.clone(),
1423                    value: false,
1424                })),
1425            )));
1426        }
1427
1428        // Handle IS DISTINCT FROM / IS NOT DISTINCT FROM
1429        if self.cur_token_is_keyword("DISTINCT") {
1430            if !self.expect_keyword("FROM") {
1431                return None;
1432            }
1433            self.next_token();
1434            let right = self.parse_expression(Precedence::Equals)?;
1435            let distinct_op = if operator == "IS" {
1436                "IS DISTINCT FROM".to_string()
1437            } else {
1438                "IS NOT DISTINCT FROM".to_string()
1439            };
1440            return Some(Expression::Infix(InfixExpression::new(
1441                token,
1442                Box::new(left),
1443                distinct_op,
1444                Box::new(right),
1445            )));
1446        }
1447
1448        self.add_error(format!(
1449            "expected NULL, TRUE, FALSE, or DISTINCT FROM after IS at {}",
1450            self.cur_token.position
1451        ));
1452        None
1453    }
1454
1455    /// Parse an IN expression
1456    fn parse_in_expression(&mut self, left: Expression, not: bool) -> Option<Expression> {
1457        let token = self.cur_token.clone();
1458
1459        if !self.peek_token_is_punctuator("(") {
1460            self.add_error(format!(
1461                "expected '(' after IN, got {}",
1462                Self::format_token_for_error(&self.peek_token)
1463            ));
1464            return None;
1465        }
1466        self.next_token();
1467
1468        // Check for subquery
1469        if self.peek_token_is_keyword("SELECT") {
1470            self.next_token();
1471            let subquery = self.parse_select_statement()?;
1472
1473            if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1474                self.add_error(format!(
1475                    "expected ')' after IN subquery at {}",
1476                    self.cur_token.position
1477                ));
1478                return None;
1479            }
1480
1481            return Some(Expression::In(InExpression {
1482                token,
1483                left: Box::new(left),
1484                right: Box::new(Expression::ScalarSubquery(ScalarSubquery {
1485                    token: self.cur_token.clone(),
1486                    subquery: Box::new(subquery),
1487                })),
1488                not,
1489            }));
1490        }
1491
1492        // Parse value list
1493        let list_token = self.cur_token.clone();
1494        self.next_token();
1495
1496        let mut expressions = Vec::new();
1497
1498        // Handle empty list
1499        if self.cur_token_is_punctuator(")") {
1500            return Some(Expression::In(InExpression {
1501                token,
1502                left: Box::new(left),
1503                right: Box::new(Expression::ExpressionList(Box::new(ExpressionList {
1504                    token: list_token,
1505                    expressions,
1506                }))),
1507                not,
1508            }));
1509        }
1510
1511        // Parse first expression
1512        if let Some(expr) = self.parse_expression(Precedence::Lowest) {
1513            expressions.push(expr);
1514        }
1515
1516        // Parse additional expressions
1517        while self.peek_token_is_punctuator(",") {
1518            self.next_token(); // consume comma
1519            self.next_token(); // move to next expression
1520
1521            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
1522                expressions.push(expr);
1523            }
1524        }
1525
1526        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1527            self.add_error(format!(
1528                "expected ')' in IN expression at {}",
1529                self.cur_token.position
1530            ));
1531            return None;
1532        }
1533
1534        Some(Expression::In(InExpression {
1535            token,
1536            left: Box::new(left),
1537            right: Box::new(Expression::ExpressionList(Box::new(ExpressionList {
1538                token: list_token,
1539                expressions,
1540            }))),
1541            not,
1542        }))
1543    }
1544
1545    /// Parse a BETWEEN expression
1546    fn parse_between_expression(&mut self, left: Expression, not: bool) -> Option<Expression> {
1547        let token = self.cur_token.clone();
1548
1549        self.next_token();
1550        let lower = self.parse_expression(Precedence::Equals)?;
1551
1552        if !self.expect_keyword("AND") {
1553            return None;
1554        }
1555
1556        self.next_token();
1557        let upper = self.parse_expression(Precedence::Equals)?;
1558
1559        Some(Expression::Between(BetweenExpression {
1560            token,
1561            expr: Box::new(left),
1562            lower: Box::new(lower),
1563            upper: Box::new(upper),
1564            not,
1565        }))
1566    }
1567
1568    /// Parse a LIKE expression with optional ESCAPE clause
1569    fn parse_like_expression(
1570        &mut self,
1571        left: Expression,
1572        op: SmartString,
1573        not: bool,
1574    ) -> Option<Expression> {
1575        let token = self.cur_token.clone();
1576        let operator = if not {
1577            SmartString::from_string(format!("NOT {}", op))
1578        } else {
1579            op
1580        };
1581        let precedence = self.cur_precedence();
1582
1583        self.next_token();
1584        let pattern = self.parse_expression(precedence)?;
1585
1586        // Check for optional ESCAPE clause
1587        let escape = if self.peek_token_is_keyword("ESCAPE") {
1588            self.next_token(); // consume ESCAPE
1589            self.next_token(); // move to escape character
1590            let escape = self.parse_expression(Precedence::Lowest)?;
1591            match &escape {
1592                Expression::StringLiteral(lit) if lit.value.chars().count() == 1 => {}
1593                _ => {
1594                    self.add_error(
1595                        "LIKE ESCAPE must be a string literal containing exactly one character"
1596                            .to_string(),
1597                    );
1598                    return None;
1599                }
1600            }
1601            Some(Box::new(escape))
1602        } else {
1603            None
1604        };
1605
1606        Some(Expression::Like(LikeExpression {
1607            token,
1608            left: Box::new(left),
1609            pattern: Box::new(pattern),
1610            operator,
1611            escape,
1612        }))
1613    }
1614
1615    /// Parse a CASE expression
1616    fn parse_case_expression(&mut self) -> Option<Expression> {
1617        let token = self.cur_token.clone();
1618        let mut value = None;
1619        let mut when_clauses = Vec::new();
1620        let mut else_value = None;
1621
1622        // Check if this is a simple CASE (with value) or searched CASE
1623        if !self.peek_token_is_keyword("WHEN") {
1624            self.next_token();
1625            value = Some(Box::new(self.parse_expression(Precedence::Lowest)?));
1626        }
1627
1628        // Parse WHEN clauses
1629        while self.peek_token_is_keyword("WHEN") {
1630            self.next_token(); // consume WHEN
1631            let when_token = self.cur_token.clone();
1632
1633            self.next_token();
1634            let condition = self.parse_expression(Precedence::Lowest)?;
1635
1636            if !self.expect_keyword("THEN") {
1637                return None;
1638            }
1639
1640            self.next_token();
1641            let then_result = self.parse_expression(Precedence::Lowest)?;
1642
1643            when_clauses.push(WhenClause {
1644                token: when_token,
1645                condition,
1646                then_result,
1647            });
1648        }
1649
1650        if when_clauses.is_empty() {
1651            self.add_error(format!(
1652                "expected at least one WHEN clause in CASE at {}",
1653                self.cur_token.position
1654            ));
1655            return None;
1656        }
1657
1658        // Parse ELSE clause
1659        if self.peek_token_is_keyword("ELSE") {
1660            self.next_token(); // consume ELSE
1661            self.next_token();
1662            else_value = Some(Box::new(self.parse_expression(Precedence::Lowest)?));
1663        }
1664
1665        if !self.expect_keyword("END") {
1666            return None;
1667        }
1668
1669        Some(Expression::Case(Box::new(CaseExpression {
1670            token,
1671            value,
1672            when_clauses,
1673            else_value,
1674        })))
1675    }
1676
1677    /// Parse a CAST expression
1678    fn parse_cast_expression(&mut self) -> Option<Expression> {
1679        let token = self.cur_token.clone();
1680
1681        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
1682            self.add_error(format!(
1683                "expected '(' after CAST at {}",
1684                self.cur_token.position
1685            ));
1686            return None;
1687        }
1688
1689        self.next_token();
1690        // Use Equals precedence to prevent AS from being consumed as an alias
1691        let expr = self.parse_expression(Precedence::Equals)?;
1692
1693        if !self.expect_keyword("AS") {
1694            return None;
1695        }
1696
1697        let type_name = self.parse_column_data_type()?;
1698        if let Err(message) = validate_cast_type_name(&type_name) {
1699            self.add_error(message);
1700            return None;
1701        }
1702
1703        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1704            self.add_error(format!(
1705                "expected ')' after type name in CAST at {}",
1706                self.cur_token.position
1707            ));
1708            return None;
1709        }
1710
1711        Some(Expression::Cast(CastExpression {
1712            token,
1713            expr: Box::new(expr),
1714            type_name,
1715        }))
1716    }
1717
1718    /// Parse an EXTRACT expression: EXTRACT(field FROM source)
1719    /// Converts to equivalent function call: YEAR(source), MONTH(source), etc.
1720    fn parse_extract_expression(&mut self) -> Option<Expression> {
1721        let token = self.cur_token.clone();
1722
1723        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
1724            self.add_error(format!(
1725                "expected '(' after EXTRACT at {}",
1726                self.cur_token.position
1727            ));
1728            return None;
1729        }
1730
1731        // Parse field name (YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, etc.)
1732        if !self.peek_token_is(TokenType::Keyword) && !self.peek_token_is(TokenType::Identifier) {
1733            self.add_error(format!(
1734                "expected field name (YEAR, MONTH, DAY, etc.) in EXTRACT at {}",
1735                self.peek_token.position
1736            ));
1737            return None;
1738        }
1739        self.next_token();
1740        let field = self.cur_token.literal.to_uppercase();
1741
1742        // Validate field name - all supported fields
1743        let valid_fields = [
1744            "YEAR",
1745            "MONTH",
1746            "DAY",
1747            "HOUR",
1748            "MINUTE",
1749            "SECOND",
1750            "DOW",
1751            "DAYOFWEEK",
1752            "ISODOW",
1753            "DOY",
1754            "DAYOFYEAR",
1755            "WEEK",
1756            "ISOWEEK",
1757            "QUARTER",
1758            "EPOCH",
1759            "MILLISECOND",
1760            "MILLISECONDS",
1761            "MICROSECOND",
1762            "MICROSECONDS",
1763        ];
1764        if !valid_fields.contains(&field.as_str()) {
1765            self.add_error(format!(
1766                "invalid EXTRACT field '{}'. Valid fields: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, DOW, DOY, WEEK, QUARTER, EPOCH, etc.",
1767                field
1768            ));
1769            return None;
1770        }
1771
1772        // Expect FROM keyword
1773        if !self.expect_keyword("FROM") {
1774            return None;
1775        }
1776
1777        // Parse source expression
1778        self.next_token();
1779        let source = self.parse_expression(Precedence::Lowest)?;
1780
1781        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1782            self.add_error(format!(
1783                "expected ')' after source in EXTRACT at {}",
1784                self.cur_token.position
1785            ));
1786            return None;
1787        }
1788
1789        // For basic fields (YEAR, MONTH, DAY, HOUR, MINUTE, SECOND), convert to direct function call
1790        // For other fields (DOW, DOY, WEEK, etc.), call EXTRACT(field_str, source)
1791        let basic_fields = ["YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND"];
1792        if basic_fields.contains(&field.as_str()) {
1793            Some(Expression::FunctionCall(Box::new(FunctionCall {
1794                token,
1795                function: field,
1796                arguments: vec![source],
1797                is_distinct: false,
1798                order_by: Vec::new(),
1799                filter: None,
1800            })))
1801        } else {
1802            // Call EXTRACT with field name as string argument
1803            let field_literal = Expression::StringLiteral(StringLiteral {
1804                token: Token {
1805                    token_type: TokenType::String,
1806                    literal: field.to_lowercase(),
1807                    position: token.position,
1808                    quoted: false,
1809                },
1810                value: field.to_lowercase(),
1811                type_hint: None,
1812            });
1813            Some(Expression::FunctionCall(Box::new(FunctionCall {
1814                token,
1815                function: SmartString::const_new("EXTRACT"),
1816                arguments: vec![field_literal, source],
1817                is_distinct: false,
1818                order_by: Vec::new(),
1819                filter: None,
1820            })))
1821        }
1822    }
1823
1824    /// Parse an EXISTS expression
1825    fn parse_exists_expression(&mut self) -> Option<Expression> {
1826        let token = self.cur_token.clone();
1827
1828        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
1829            self.add_error(format!(
1830                "expected '(' after EXISTS at {}",
1831                self.cur_token.position
1832            ));
1833            return None;
1834        }
1835
1836        self.next_token();
1837        if !self.cur_token_is_keyword("SELECT") {
1838            self.add_error(format!(
1839                "expected SELECT in EXISTS subquery at {}",
1840                self.cur_token.position
1841            ));
1842            return None;
1843        }
1844
1845        let subquery = self.parse_select_statement()?;
1846
1847        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
1848            self.add_error(format!(
1849                "expected ')' after EXISTS subquery at {}",
1850                self.cur_token.position
1851            ));
1852            return None;
1853        }
1854
1855        Some(Expression::Exists(ExistsExpression {
1856            token,
1857            subquery: Box::new(subquery),
1858        }))
1859    }
1860
1861    /// Parse a NOT expression
1862    fn parse_not_expression(&mut self) -> Option<Expression> {
1863        let token = self.cur_token.clone();
1864
1865        // Check for NOT EXISTS
1866        if self.peek_token_is_keyword("EXISTS") {
1867            self.next_token();
1868            let exists_expr = self.parse_exists_expression()?;
1869            return Some(Expression::Prefix(PrefixExpression::new(
1870                token,
1871                "NOT".to_string(),
1872                Box::new(exists_expr),
1873            )));
1874        }
1875
1876        self.next_token();
1877        // Use Precedence::Not (lower than comparison) so NOT captures the full comparison
1878        // This makes "NOT category = 'Electronics'" parse as "NOT (category = 'Electronics')"
1879        let right = self.parse_expression(Precedence::Not)?;
1880
1881        Some(Expression::Prefix(PrefixExpression::new(
1882            token,
1883            "NOT".to_string(),
1884            Box::new(right),
1885        )))
1886    }
1887
1888    /// Parse an INTERVAL literal
1889    /// Supports two syntaxes:
1890    /// - INTERVAL '1 month' (quoted string)
1891    /// - INTERVAL 1 MONTH (integer followed by unit keyword)
1892    fn parse_interval_literal(&mut self) -> Option<Expression> {
1893        let token = self.cur_token.clone();
1894
1895        // Check if the next token is an integer (unquoted syntax) or string (quoted syntax)
1896        if self.peek_token_is(TokenType::Integer) {
1897            // INTERVAL 1 MONTH syntax
1898            self.next_token();
1899            let quantity = match self.cur_token.literal.parse::<i64>() {
1900                Ok(q) => q,
1901                Err(_) => {
1902                    self.add_error(format!(
1903                        "invalid interval quantity: {} at {}",
1904                        self.cur_token.literal, self.cur_token.position
1905                    ));
1906                    return None;
1907                }
1908            };
1909
1910            // Expect a unit keyword (SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR)
1911            self.next_token();
1912            let unit_raw = self.cur_token.literal.to_uppercase();
1913            let unit = match unit_raw.as_str() {
1914                "SECOND" | "SECONDS" => "second",
1915                "MINUTE" | "MINUTES" => "minute",
1916                "HOUR" | "HOURS" => "hour",
1917                "DAY" | "DAYS" => "day",
1918                "WEEK" | "WEEKS" => "week",
1919                "MONTH" | "MONTHS" => "month",
1920                "YEAR" | "YEARS" => "year",
1921                _ => {
1922                    self.add_error(format!(
1923                        "invalid interval unit: {} at {}. Expected SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, or YEAR",
1924                        self.cur_token.literal, self.cur_token.position
1925                    ));
1926                    return None;
1927                }
1928            };
1929
1930            let value = SmartString::from_string(format!("{} {}", quantity, unit));
1931            Some(Expression::IntervalLiteral(IntervalLiteral {
1932                token,
1933                value,
1934                quantity,
1935                unit: SmartString::new(unit),
1936            }))
1937        } else if self.expect_peek(TokenType::String) {
1938            // INTERVAL '1 month' syntax (original)
1939            let literal = &self.cur_token.literal;
1940            let value_str = if literal.len() >= 2 {
1941                &literal[1..literal.len() - 1]
1942            } else {
1943                literal.as_str()
1944            };
1945
1946            // Parse the interval value
1947            let parts: Vec<&str> = value_str.split_whitespace().collect();
1948            if parts.len() != 2 {
1949                self.add_error(format!(
1950                    "invalid interval format: {} at {}",
1951                    value_str, self.cur_token.position
1952                ));
1953                return None;
1954            }
1955
1956            let quantity = match parts[0].parse::<i64>() {
1957                Ok(q) => q,
1958                Err(_) => {
1959                    self.add_error(format!(
1960                        "invalid interval quantity: {} at {}",
1961                        parts[0], self.cur_token.position
1962                    ));
1963                    return None;
1964                }
1965            };
1966
1967            let unit_raw = parts[1].to_ascii_uppercase();
1968            let unit = match unit_raw.as_str() {
1969                "SECOND" | "SECONDS" => "second",
1970                "MINUTE" | "MINUTES" => "minute",
1971                "HOUR" | "HOURS" => "hour",
1972                "DAY" | "DAYS" => "day",
1973                "WEEK" | "WEEKS" => "week",
1974                "MONTH" | "MONTHS" => "month",
1975                "YEAR" | "YEARS" => "year",
1976                _ => {
1977                    self.add_error(format!(
1978                        "invalid interval unit: {} at {}. Expected SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, or YEAR",
1979                        parts[1], self.cur_token.position
1980                    ));
1981                    return None;
1982                }
1983            };
1984
1985            Some(Expression::IntervalLiteral(IntervalLiteral {
1986                token,
1987                value: SmartString::from(value_str),
1988                quantity,
1989                unit: SmartString::new(unit),
1990            }))
1991        } else {
1992            None
1993        }
1994    }
1995
1996    /// Parse a typed literal (TIMESTAMP '...', DATE '...', TIME '...')
1997    fn parse_typed_literal(&mut self) -> Option<Expression> {
1998        let type_hint = self.cur_token.literal.clone();
1999
2000        if !self.peek_token_is(TokenType::String) {
2001            self.add_error(format!(
2002                "expected string literal after {} at {}",
2003                type_hint, self.cur_token.position
2004            ));
2005            return None;
2006        }
2007
2008        self.next_token();
2009
2010        let literal = &self.cur_token.literal;
2011        let value = if literal.len() >= 2 && literal.starts_with('\'') && literal.ends_with('\'') {
2012            SmartString::from(&literal[1..literal.len() - 1])
2013        } else {
2014            literal.clone()
2015        };
2016
2017        Some(Expression::StringLiteral(StringLiteral {
2018            token: self.cur_token.clone(),
2019            value,
2020            type_hint: Some(type_hint),
2021        }))
2022    }
2023
2024    /// Parse an expression list (comma-separated)
2025    pub fn parse_expression_list(&mut self) -> Vec<Expression> {
2026        // Pre-allocate for common case (most expression lists have 1-8 elements)
2027        let mut list = Vec::with_capacity(8);
2028
2029        self.next_token();
2030        if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2031            list.push(expr);
2032        }
2033
2034        while self.peek_token_is_punctuator(",") {
2035            self.next_token(); // consume comma
2036            self.next_token();
2037            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2038                list.push(expr);
2039            }
2040        }
2041
2042        list
2043    }
2044
2045    /// Parse a GROUP BY clause with optional ROLLUP/CUBE/GROUPING SETS modifier
2046    pub fn parse_group_by_clause(&mut self) -> GroupByClause {
2047        use crate::ast::{GroupByClause, GroupByModifier};
2048
2049        self.next_token();
2050
2051        // Check for ROLLUP, CUBE, or GROUPING SETS
2052        let modifier = if self.cur_token.token_type == TokenType::Identifier
2053            || self.cur_token.token_type == TokenType::Keyword
2054        {
2055            let upper = self.cur_token.literal.to_uppercase();
2056            if upper == "ROLLUP" {
2057                self.next_token(); // consume ROLLUP
2058                                   // Expect opening paren
2059                if self.cur_token.literal == "(" {
2060                    self.next_token(); // consume (
2061                    let columns = self.parse_group_by_columns();
2062                    // cur_token should now be at ), don't advance past it
2063                    // to maintain consistency with regular GROUP BY parsing
2064                    // where peek_token points to next clause keyword (ORDER, HAVING, etc.)
2065                    return GroupByClause {
2066                        columns,
2067                        modifier: GroupByModifier::Rollup,
2068                    };
2069                }
2070                GroupByModifier::None
2071            } else if upper == "CUBE" {
2072                self.next_token(); // consume CUBE
2073                                   // Expect opening paren
2074                if self.cur_token.literal == "(" {
2075                    self.next_token(); // consume (
2076                    let columns = self.parse_group_by_columns();
2077                    // cur_token should now be at ), don't advance past it
2078                    // to maintain consistency with regular GROUP BY parsing
2079                    return GroupByClause {
2080                        columns,
2081                        modifier: GroupByModifier::Cube,
2082                    };
2083                }
2084                GroupByModifier::None
2085            } else if upper == "GROUPING" {
2086                // Check for GROUPING SETS
2087                if self.peek_token.literal.to_uppercase() == "SETS" {
2088                    self.next_token(); // consume GROUPING
2089                    self.next_token(); // consume SETS
2090                                       // Expect opening paren for the outer grouping sets list
2091                    if self.cur_token.literal == "(" {
2092                        self.next_token(); // consume (
2093                        let sets = self.parse_grouping_sets();
2094                        // cur_token should now be at )
2095                        return GroupByClause {
2096                            columns: Vec::new(),
2097                            modifier: GroupByModifier::GroupingSets(sets),
2098                        };
2099                    }
2100                }
2101                GroupByModifier::None
2102            } else {
2103                GroupByModifier::None
2104            }
2105        } else {
2106            GroupByModifier::None
2107        };
2108
2109        // Regular GROUP BY (no ROLLUP/CUBE/GROUPING SETS)
2110        let mut columns = Vec::new();
2111        if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2112            columns.push(expr);
2113        }
2114
2115        while self.peek_token_is_punctuator(",") {
2116            self.next_token(); // consume comma
2117            self.next_token();
2118            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2119                columns.push(expr);
2120            }
2121        }
2122
2123        GroupByClause { columns, modifier }
2124    }
2125
2126    /// Parse columns inside ROLLUP() or CUBE()
2127    fn parse_group_by_columns(&mut self) -> Vec<Expression> {
2128        let mut columns = Vec::new();
2129
2130        if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2131            columns.push(expr);
2132        }
2133
2134        while self.peek_token_is_punctuator(",") {
2135            self.next_token(); // consume comma
2136            self.next_token();
2137            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2138                columns.push(expr);
2139            }
2140        }
2141
2142        // Move past the last expression to the )
2143        if self.peek_token_is_punctuator(")") {
2144            self.next_token();
2145        }
2146
2147        columns
2148    }
2149
2150    /// Parse GROUPING SETS content: ((col1, col2), (col1), ())
2151    /// Returns a Vec of Vec<Expression>, where each inner Vec is one grouping set
2152    fn parse_grouping_sets(&mut self) -> Vec<Vec<Expression>> {
2153        let mut sets = Vec::new();
2154
2155        // Parse first set (must be there)
2156        if self.cur_token.literal == "(" {
2157            sets.push(self.parse_single_grouping_set());
2158        }
2159
2160        // Parse additional sets separated by comma
2161        while self.cur_token.literal == "," {
2162            self.next_token(); // consume comma
2163            if self.cur_token.literal == "(" {
2164                sets.push(self.parse_single_grouping_set());
2165            }
2166        }
2167
2168        // cur_token should be at the closing ) of GROUPING SETS
2169        sets
2170    }
2171
2172    /// Parse a single grouping set: (col1, col2) or ()
2173    fn parse_single_grouping_set(&mut self) -> Vec<Expression> {
2174        let mut columns = Vec::new();
2175
2176        self.next_token(); // consume opening (
2177
2178        // Check for empty set ()
2179        if self.cur_token.literal == ")" {
2180            self.next_token(); // consume )
2181            return columns;
2182        }
2183
2184        // Parse first column
2185        if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2186            columns.push(expr);
2187        }
2188
2189        // Parse additional columns separated by comma within this set
2190        while self.peek_token_is_punctuator(",") {
2191            self.next_token(); // move to comma
2192            self.next_token(); // move past comma to next expression
2193            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2194                columns.push(expr);
2195            }
2196        }
2197
2198        // Advance to the closing ) if not already there, then move past it
2199        if self.peek_token_is_punctuator(")") {
2200            self.next_token(); // move to )
2201        }
2202        self.next_token(); // move past )
2203
2204        columns
2205    }
2206
2207    /// Parse WINDOW clause definitions (WINDOW w AS (...), w2 AS (...))
2208    pub fn parse_window_definitions(&mut self) -> Vec<WindowDefinition> {
2209        let mut defs = Vec::new();
2210
2211        // First window definition
2212        if let Some(def) = self.parse_single_window_definition() {
2213            defs.push(def);
2214        }
2215
2216        // Additional window definitions separated by comma
2217        while self.peek_token_is_punctuator(",") {
2218            self.next_token(); // consume comma
2219            self.next_token(); // move to next window name
2220            if let Some(def) = self.parse_single_window_definition() {
2221                defs.push(def);
2222            }
2223        }
2224
2225        defs
2226    }
2227
2228    /// Parse a single window definition: name AS (partition/order/frame)
2229    fn parse_single_window_definition(&mut self) -> Option<WindowDefinition> {
2230        self.next_token(); // move to window name
2231
2232        // Get window name
2233        let name = if self.cur_token_is(TokenType::Identifier) {
2234            self.cur_token.literal.clone()
2235        } else if self.cur_token_is(TokenType::Keyword) {
2236            // Allow keywords as window names
2237            self.cur_token.literal.clone()
2238        } else {
2239            self.add_error(format!(
2240                "expected window name at {}",
2241                self.cur_token.position
2242            ));
2243            return None;
2244        };
2245
2246        // Expect AS keyword
2247        if !self.expect_keyword("AS") {
2248            return None;
2249        }
2250
2251        // Expect opening parenthesis
2252        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != "(" {
2253            self.add_error(format!(
2254                "expected '(' after AS in window definition at {}",
2255                self.cur_token.position
2256            ));
2257            return None;
2258        }
2259
2260        let mut partition_by = Vec::new();
2261        let mut order_by = Vec::new();
2262        let mut frame = None;
2263
2264        // Parse PARTITION BY
2265        if self.peek_token_is_keyword("PARTITION") {
2266            self.next_token(); // consume PARTITION
2267            if !self.expect_keyword("BY") {
2268                return None;
2269            }
2270
2271            self.next_token();
2272            if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2273                partition_by.push(expr);
2274            }
2275
2276            while self.peek_token_is_punctuator(",") {
2277                self.next_token(); // consume comma
2278                self.next_token();
2279                if let Some(expr) = self.parse_expression(Precedence::Lowest) {
2280                    partition_by.push(expr);
2281                }
2282            }
2283        }
2284
2285        // Parse ORDER BY
2286        if self.peek_token_is_keyword("ORDER") {
2287            self.next_token(); // consume ORDER
2288            if !self.expect_keyword("BY") {
2289                return None;
2290            }
2291
2292            self.next_token();
2293            if let Some(order_expr) = self.parse_order_by_expression() {
2294                order_by.push(order_expr);
2295            }
2296
2297            while self.peek_token_is_punctuator(",") {
2298                self.next_token(); // consume comma
2299                self.next_token();
2300                if let Some(order_expr) = self.parse_order_by_expression() {
2301                    order_by.push(order_expr);
2302                }
2303            }
2304        }
2305
2306        // Parse window frame (ROWS/RANGE)
2307        if self.peek_token_is_keyword("ROWS") || self.peek_token_is_keyword("RANGE") {
2308            frame = self.parse_window_frame();
2309        }
2310
2311        // Expect closing parenthesis
2312        if !self.expect_peek(TokenType::Punctuator) || self.cur_token.literal != ")" {
2313            self.add_error(format!(
2314                "expected ')' after window specification at {}",
2315                self.cur_token.position
2316            ));
2317            return None;
2318        }
2319
2320        Some(WindowDefinition {
2321            name,
2322            partition_by,
2323            order_by,
2324            frame,
2325        })
2326    }
2327
2328    /// Parse an ORDER BY expression
2329    pub fn parse_order_by_expression(&mut self) -> Option<OrderByExpression> {
2330        let expression = self.parse_expression(Precedence::Lowest)?;
2331
2332        let mut ascending = true;
2333        if self.peek_token_is_keyword("ASC") {
2334            self.next_token();
2335            ascending = true;
2336        } else if self.peek_token_is_keyword("DESC") {
2337            self.next_token();
2338            ascending = false;
2339        }
2340
2341        // Parse optional NULLS FIRST / NULLS LAST
2342        let nulls_first = if self.peek_token_is_keyword("NULLS") {
2343            self.next_token(); // consume NULLS
2344            if self.peek_token_is_keyword("FIRST") {
2345                self.next_token(); // consume FIRST
2346                Some(true)
2347            } else if self.peek_token_is_keyword("LAST") {
2348                self.next_token(); // consume LAST
2349                Some(false)
2350            } else {
2351                self.add_error(format!(
2352                    "expected FIRST or LAST after NULLS at {}",
2353                    self.peek_token.position
2354                ));
2355                return None;
2356            }
2357        } else {
2358            None
2359        };
2360
2361        Some(OrderByExpression {
2362            expression,
2363            ascending,
2364            nulls_first,
2365        })
2366    }
2367
2368    /// Parse ORDER BY expressions (comma-separated)
2369    pub fn parse_order_by_expressions(&mut self) -> Vec<OrderByExpression> {
2370        let mut list = Vec::new();
2371
2372        self.next_token();
2373        if let Some(expr) = self.parse_order_by_expression() {
2374            list.push(expr);
2375        }
2376
2377        while self.peek_token_is_punctuator(",") {
2378            self.next_token(); // consume comma
2379            self.next_token();
2380            if let Some(expr) = self.parse_order_by_expression() {
2381                list.push(expr);
2382            }
2383        }
2384
2385        list
2386    }
2387}
2388
2389#[cfg(test)]
2390mod tests {
2391    use super::*;
2392
2393    fn parse_expr(input: &str) -> Option<Expression> {
2394        let mut parser = Parser::new(input);
2395        parser.parse_expression(Precedence::Lowest)
2396    }
2397
2398    #[test]
2399    fn test_parse_identifier() {
2400        let expr = parse_expr("users").unwrap();
2401        match expr {
2402            Expression::Identifier(id) => assert_eq!(id.value, "users"),
2403            _ => panic!("expected Identifier"),
2404        }
2405    }
2406
2407    #[test]
2408    fn test_parse_integer() {
2409        let expr = parse_expr("42").unwrap();
2410        match expr {
2411            Expression::IntegerLiteral(lit) => assert_eq!(lit.value, 42),
2412            _ => panic!("expected IntegerLiteral"),
2413        }
2414    }
2415
2416    #[test]
2417    fn test_parse_integer_i64_boundaries() {
2418        let mut max_parser = Parser::new("9223372036854775807");
2419        let max_expr = max_parser
2420            .parse_expression(Precedence::Lowest)
2421            .expect("i64::MAX should parse as an integer literal");
2422        assert!(max_parser.errors().is_empty());
2423        match max_expr {
2424            Expression::IntegerLiteral(lit) => assert_eq!(lit.value, i64::MAX),
2425            other => panic!("expected IntegerLiteral, got {other:?}"),
2426        }
2427
2428        let mut min_parser = Parser::new("-9223372036854775808");
2429        let min_expr = min_parser
2430            .parse_expression(Precedence::Lowest)
2431            .expect("i64::MIN should parse through the unary-minus special case");
2432        assert!(min_parser.errors().is_empty());
2433        match min_expr {
2434            Expression::IntegerLiteral(lit) => assert_eq!(lit.value, i64::MIN),
2435            other => panic!("expected IntegerLiteral, got {other:?}"),
2436        }
2437    }
2438
2439    #[test]
2440    fn test_parse_integer_overflow_is_an_error() {
2441        for literal in ["9223372036854775808", "-9223372036854775809"] {
2442            let mut parser = Parser::new(literal);
2443            let expression = parser.parse_expression(Precedence::Lowest);
2444
2445            assert!(expression.is_none(), "{literal} must not produce an AST");
2446            assert_eq!(
2447                parser.errors().len(),
2448                1,
2449                "{literal} must produce exactly one parser error"
2450            );
2451            assert!(
2452                parser.errors()[0]
2453                    .message
2454                    .contains("is out of range for i64"),
2455                "unexpected parser error for {literal}: {}",
2456                parser.errors()[0].message
2457            );
2458        }
2459    }
2460
2461    #[test]
2462    fn test_parse_float() {
2463        let expr = parse_expr("3.5").unwrap();
2464        match expr {
2465            Expression::FloatLiteral(lit) => assert!((lit.value - 3.5).abs() < 0.001),
2466            _ => panic!("expected FloatLiteral"),
2467        }
2468    }
2469
2470    #[test]
2471    fn test_parse_string() {
2472        let expr = parse_expr("'hello'").unwrap();
2473        match expr {
2474            Expression::StringLiteral(lit) => assert_eq!(lit.value, "hello"),
2475            _ => panic!("expected StringLiteral"),
2476        }
2477    }
2478
2479    #[test]
2480    fn test_parse_boolean() {
2481        let expr = parse_expr("TRUE").unwrap();
2482        match expr {
2483            Expression::BooleanLiteral(lit) => assert!(lit.value),
2484            _ => panic!("expected BooleanLiteral"),
2485        }
2486
2487        let expr = parse_expr("FALSE").unwrap();
2488        match expr {
2489            Expression::BooleanLiteral(lit) => assert!(!lit.value),
2490            _ => panic!("expected BooleanLiteral"),
2491        }
2492    }
2493
2494    #[test]
2495    fn test_parse_null() {
2496        let expr = parse_expr("NULL").unwrap();
2497        match expr {
2498            Expression::NullLiteral(_) => {}
2499            _ => panic!("expected NullLiteral"),
2500        }
2501    }
2502
2503    #[test]
2504    fn test_parse_infix() {
2505        let expr = parse_expr("1 + 2").unwrap();
2506        match expr {
2507            Expression::Infix(infix) => {
2508                assert_eq!(infix.operator, "+");
2509            }
2510            _ => panic!("expected InfixExpression"),
2511        }
2512    }
2513
2514    #[test]
2515    fn test_parse_precedence() {
2516        let expr = parse_expr("1 + 2 * 3").unwrap();
2517        // Should be parsed as 1 + (2 * 3)
2518        match expr {
2519            Expression::Infix(infix) => {
2520                assert_eq!(infix.operator, "+");
2521                match infix.right.as_ref() {
2522                    Expression::Infix(right) => {
2523                        assert_eq!(right.operator, "*");
2524                    }
2525                    _ => panic!("expected nested InfixExpression"),
2526                }
2527            }
2528            _ => panic!("expected InfixExpression"),
2529        }
2530    }
2531
2532    #[test]
2533    fn test_expression_stops_before_statement_owned_alias() {
2534        let mut parser = Parser::new("1 AS answer");
2535        let expression = parser
2536            .parse_expression(Precedence::Lowest)
2537            .expect("integer expression should parse");
2538
2539        assert!(matches!(expression, Expression::IntegerLiteral(_)));
2540        assert!(parser.peek_token_is_keyword("AS"));
2541    }
2542
2543    #[test]
2544    fn test_parse_qualified_identifier() {
2545        let expr = parse_expr("users.id").unwrap();
2546        match expr {
2547            Expression::QualifiedIdentifier(qi) => {
2548                assert_eq!(qi.qualifier.value, "users");
2549                assert!(qi.intermediate.is_none());
2550                assert_eq!(qi.name.value, "id");
2551                assert_eq!(qi.component_count(), 2);
2552            }
2553            _ => panic!("expected QualifiedIdentifier"),
2554        }
2555    }
2556
2557    #[test]
2558    fn test_parse_multi_part_identifier_path_preserves_components_and_positions() {
2559        let expr = parse_expr("m.sender_id.profile_id.display_name").unwrap();
2560        let Expression::QualifiedIdentifier(path) = expr else {
2561            panic!("expected unresolved multi-part QualifiedIdentifier");
2562        };
2563
2564        let components: Vec<_> = path
2565            .components()
2566            .map(|component| {
2567                (
2568                    component.value().to_string(),
2569                    component.token.position.column,
2570                )
2571            })
2572            .collect();
2573        assert_eq!(
2574            components,
2575            vec![
2576                ("m".to_string(), 1),
2577                ("sender_id".to_string(), 3),
2578                ("profile_id".to_string(), 13),
2579                ("display_name".to_string(), 24),
2580            ]
2581        );
2582        assert_eq!(path.component_count(), 4);
2583        assert!(path.is_multi_part_path());
2584        assert_eq!(path.to_string(), "m.sender_id.profile_id.display_name");
2585    }
2586
2587    #[test]
2588    fn test_parse_identifier_path_supports_eight_components_and_roundtrip() {
2589        let sql = "a.b.c.d.e.f.g.h";
2590        let expr = parse_expr(sql).unwrap();
2591        let Expression::QualifiedIdentifier(path) = &expr else {
2592            panic!("expected eight-component path");
2593        };
2594        assert_eq!(path.component_count(), 8);
2595        assert_eq!(expr.to_string(), sql);
2596
2597        let reparsed = parse_expr(&expr.to_string()).unwrap();
2598        let Expression::QualifiedIdentifier(reparsed) = reparsed else {
2599            panic!("expected round-tripped path");
2600        };
2601        let values: Vec<_> = reparsed
2602            .components()
2603            .map(|component| component.value().to_string())
2604            .collect();
2605        assert_eq!(values, ["a", "b", "c", "d", "e", "f", "g", "h"]);
2606    }
2607
2608    #[test]
2609    fn test_parse_identifier_path_preserves_quoted_and_keyword_components() {
2610        let expr = parse_expr("\"Root\".type.\"Target Field\"").unwrap();
2611        let Expression::QualifiedIdentifier(path) = expr else {
2612            panic!("expected quoted identifier path");
2613        };
2614        let values: Vec<_> = path
2615            .components()
2616            .map(|component| component.value().to_string())
2617            .collect();
2618        assert_eq!(values, ["Root", "type", "Target Field"]);
2619        assert_eq!(path.to_string(), "\"Root\".type.\"Target Field\"");
2620    }
2621
2622    #[test]
2623    fn test_multi_part_qualified_star_is_rejected_without_breaking_table_star() {
2624        assert!(matches!(
2625            parse_expr("users.*").unwrap(),
2626            Expression::QualifiedStar(_)
2627        ));
2628
2629        let mut parser = Parser::new("users.profile_id.*");
2630        assert!(parser.parse_expression(Precedence::Lowest).is_none());
2631        assert!(parser
2632            .errors()
2633            .iter()
2634            .any(|error| error.message.contains("qualified star cannot follow")));
2635    }
2636
2637    #[test]
2638    fn test_parse_function_call() {
2639        let expr = parse_expr("COUNT(*)").unwrap();
2640        match expr {
2641            Expression::FunctionCall(fc) => {
2642                assert_eq!(fc.function, "COUNT");
2643                assert_eq!(fc.arguments.len(), 1);
2644            }
2645            _ => panic!("expected FunctionCall"),
2646        }
2647    }
2648
2649    #[test]
2650    fn test_parse_count_star_with_filter() {
2651        let expr = parse_expr("COUNT(*) FILTER (WHERE x = 1)").unwrap();
2652        match expr {
2653            Expression::FunctionCall(fc) => {
2654                assert_eq!(fc.function, "COUNT");
2655                assert_eq!(fc.arguments.len(), 1);
2656                assert!(
2657                    fc.filter.is_some(),
2658                    "FILTER clause should be parsed for COUNT(*)"
2659                );
2660            }
2661            _ => panic!("expected FunctionCall"),
2662        }
2663    }
2664
2665    #[test]
2666    fn test_parse_function_call_with_multiple_args() {
2667        let expr = parse_expr("STRING_AGG(name, '; ')").unwrap();
2668        match expr {
2669            Expression::FunctionCall(fc) => {
2670                assert_eq!(fc.function, "STRING_AGG");
2671                assert_eq!(
2672                    fc.arguments.len(),
2673                    2,
2674                    "Expected 2 arguments, got: {:?}",
2675                    fc.arguments
2676                );
2677                // First argument should be an identifier
2678                match &fc.arguments[0] {
2679                    Expression::Identifier(id) => assert_eq!(id.value, "name"),
2680                    other => panic!("Expected Identifier, got: {:?}", other),
2681                }
2682                // Second argument should be a string literal
2683                match &fc.arguments[1] {
2684                    Expression::StringLiteral(lit) => assert_eq!(lit.value, "; "),
2685                    other => panic!("Expected StringLiteral, got: {:?}", other),
2686                }
2687            }
2688            _ => panic!("expected FunctionCall"),
2689        }
2690    }
2691
2692    #[test]
2693    fn test_parse_is_null() {
2694        let expr = parse_expr("x IS NULL").unwrap();
2695        match expr {
2696            Expression::Infix(infix) => {
2697                assert_eq!(infix.operator, "IS");
2698            }
2699            _ => panic!("expected InfixExpression"),
2700        }
2701    }
2702
2703    #[test]
2704    fn test_parse_is_not_null() {
2705        let expr = parse_expr("x IS NOT NULL").unwrap();
2706        match expr {
2707            Expression::Infix(infix) => {
2708                assert_eq!(infix.operator, "IS NOT");
2709            }
2710            _ => panic!("expected InfixExpression"),
2711        }
2712    }
2713
2714    #[test]
2715    fn test_parse_in() {
2716        let expr = parse_expr("x IN (1, 2, 3)").unwrap();
2717        match expr {
2718            Expression::In(in_expr) => {
2719                assert!(!in_expr.not);
2720            }
2721            _ => panic!("expected InExpression"),
2722        }
2723    }
2724
2725    #[test]
2726    fn test_parse_not_in() {
2727        let expr = parse_expr("x NOT IN (1, 2, 3)").unwrap();
2728        match expr {
2729            Expression::In(in_expr) => {
2730                assert!(in_expr.not);
2731            }
2732            _ => panic!("expected InExpression"),
2733        }
2734    }
2735
2736    #[test]
2737    fn test_parse_between() {
2738        let expr = parse_expr("x BETWEEN 1 AND 10").unwrap();
2739        match expr {
2740            Expression::Between(between) => {
2741                assert!(!between.not);
2742            }
2743            _ => panic!("expected BetweenExpression"),
2744        }
2745    }
2746
2747    #[test]
2748    fn test_parse_case() {
2749        let expr = parse_expr("CASE WHEN x = 1 THEN 'one' ELSE 'other' END").unwrap();
2750        match expr {
2751            Expression::Case(case) => {
2752                assert!(case.value.is_none());
2753                assert_eq!(case.when_clauses.len(), 1);
2754                assert!(case.else_value.is_some());
2755            }
2756            _ => panic!("expected CaseExpression"),
2757        }
2758    }
2759
2760    #[test]
2761    fn test_parse_cast() {
2762        let expr = parse_expr("CAST(x AS INTEGER)").unwrap();
2763        match expr {
2764            Expression::Cast(cast) => {
2765                assert_eq!(cast.type_name, "INTEGER");
2766            }
2767            _ => panic!("expected CastExpression"),
2768        }
2769    }
2770}