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