sql_cli/sql/
recursive_parser.rs

1// Keep chrono imports for the parser implementation
2
3// Re-exports for backward compatibility - these serve as both imports and re-exports
4pub use super::parser::ast::{
5    CTEType, Condition, DataFormat, FrameBound, FrameUnit, HttpMethod, IntoTable, JoinClause,
6    JoinCondition, JoinOperator, JoinType, LogicalOp, OrderByColumn, SelectItem, SelectStatement,
7    SingleJoinCondition, SortDirection, SqlExpression, TableFunction, TableSource, WebCTESpec,
8    WhenBranch, WhereClause, WindowFrame, WindowSpec, CTE,
9};
10pub use super::parser::legacy::{ParseContext, ParseState, Schema, SqlParser, SqlToken, TableInfo};
11pub use super::parser::lexer::{Lexer, Token};
12pub use super::parser::ParserConfig;
13
14// Re-export formatting functions for backward compatibility
15pub use super::parser::formatter::{format_ast_tree, format_sql_pretty, format_sql_pretty_compact};
16
17// New AST-based formatter
18pub use super::parser::ast_formatter::{format_sql_ast, format_sql_ast_with_config, FormatConfig};
19
20// Import the new expression modules
21use super::parser::expressions::arithmetic::{
22    parse_additive as parse_additive_expr, parse_multiplicative as parse_multiplicative_expr,
23    ParseArithmetic,
24};
25use super::parser::expressions::case::{parse_case_expression as parse_case_expr, ParseCase};
26use super::parser::expressions::comparison::{
27    parse_comparison as parse_comparison_expr, parse_in_operator, ParseComparison,
28};
29use super::parser::expressions::logical::{
30    parse_logical_and as parse_logical_and_expr, parse_logical_or as parse_logical_or_expr,
31    ParseLogical,
32};
33use super::parser::expressions::primary::{
34    parse_primary as parse_primary_expr, ParsePrimary, PrimaryExpressionContext,
35};
36use super::parser::expressions::ExpressionParser;
37
38// Import function registry to check for function existence
39use crate::sql::functions::{FunctionCategory, FunctionRegistry};
40use crate::sql::generators::GeneratorRegistry;
41use std::sync::Arc;
42
43// Import Web CTE parser
44use super::parser::web_cte_parser::WebCteParser;
45pub struct Parser {
46    lexer: Lexer,
47    pub current_token: Token,    // Made public for web_cte_parser access
48    in_method_args: bool,        // Track if we're parsing method arguments
49    columns: Vec<String>,        // Known column names for context-aware parsing
50    paren_depth: i32,            // Track parentheses nesting depth
51    paren_depth_stack: Vec<i32>, // Stack to save/restore paren depth for nested contexts
52    _config: ParserConfig,       // Parser configuration including case sensitivity
53    debug_trace: bool,           // Enable detailed token-by-token trace
54    trace_depth: usize,          // Track recursion depth for indented trace
55    function_registry: Arc<FunctionRegistry>, // Function registry for validation
56    generator_registry: Arc<GeneratorRegistry>, // Generator registry for table functions
57}
58
59impl Parser {
60    #[must_use]
61    pub fn new(input: &str) -> Self {
62        let mut lexer = Lexer::new(input);
63        let current_token = lexer.next_token();
64        Self {
65            lexer,
66            current_token,
67            in_method_args: false,
68            columns: Vec::new(),
69            paren_depth: 0,
70            paren_depth_stack: Vec::new(),
71            _config: ParserConfig::default(),
72            debug_trace: false,
73            trace_depth: 0,
74            function_registry: Arc::new(FunctionRegistry::new()),
75            generator_registry: Arc::new(GeneratorRegistry::new()),
76        }
77    }
78
79    #[must_use]
80    pub fn with_config(input: &str, config: ParserConfig) -> Self {
81        let mut lexer = Lexer::new(input);
82        let current_token = lexer.next_token();
83        Self {
84            lexer,
85            current_token,
86            in_method_args: false,
87            columns: Vec::new(),
88            paren_depth: 0,
89            paren_depth_stack: Vec::new(),
90            _config: config,
91            debug_trace: false,
92            trace_depth: 0,
93            function_registry: Arc::new(FunctionRegistry::new()),
94            generator_registry: Arc::new(GeneratorRegistry::new()),
95        }
96    }
97
98    #[must_use]
99    pub fn with_columns(mut self, columns: Vec<String>) -> Self {
100        self.columns = columns;
101        self
102    }
103
104    #[must_use]
105    pub fn with_debug_trace(mut self, enabled: bool) -> Self {
106        self.debug_trace = enabled;
107        self
108    }
109
110    #[must_use]
111    pub fn with_function_registry(mut self, registry: Arc<FunctionRegistry>) -> Self {
112        self.function_registry = registry;
113        self
114    }
115
116    #[must_use]
117    pub fn with_generator_registry(mut self, registry: Arc<GeneratorRegistry>) -> Self {
118        self.generator_registry = registry;
119        self
120    }
121
122    fn trace_enter(&mut self, context: &str) {
123        if self.debug_trace {
124            let indent = "  ".repeat(self.trace_depth);
125            eprintln!("{}→ {} | Token: {:?}", indent, context, self.current_token);
126            self.trace_depth += 1;
127        }
128    }
129
130    fn trace_exit(&mut self, context: &str, result: &Result<impl std::fmt::Debug, String>) {
131        if self.debug_trace {
132            self.trace_depth = self.trace_depth.saturating_sub(1);
133            let indent = "  ".repeat(self.trace_depth);
134            match result {
135                Ok(val) => eprintln!("{}← {} ✓ | Result: {:?}", indent, context, val),
136                Err(e) => eprintln!("{}← {} ✗ | Error: {}", indent, context, e),
137            }
138        }
139    }
140
141    fn trace_token(&self, action: &str) {
142        if self.debug_trace {
143            let indent = "  ".repeat(self.trace_depth);
144            eprintln!("{}  {} | Token: {:?}", indent, action, self.current_token);
145        }
146    }
147
148    #[allow(dead_code)]
149    fn peek_token(&self) -> Option<Token> {
150        // Alternative peek that returns owned token
151        let mut temp_lexer = self.lexer.clone();
152        let next_token = temp_lexer.next_token();
153        if matches!(next_token, Token::Eof) {
154            None
155        } else {
156            Some(next_token)
157        }
158    }
159
160    /// Check if current token is one of the reserved keywords that should stop parsing
161    /// Check if an identifier string is a reserved keyword (for backward compatibility)
162    /// This is used when the lexer hasn't properly tokenized keywords and they come through
163    /// as Token::Identifier instead of their proper token types
164    fn is_identifier_reserved(id: &str) -> bool {
165        let id_upper = id.to_uppercase();
166        matches!(
167            id_upper.as_str(),
168            "ORDER" | "HAVING" | "LIMIT" | "OFFSET" | "UNION" | "INTERSECT" | "EXCEPT"
169        )
170    }
171
172    /// Get comparison operator string representation (for autocomplete context)
173    const COMPARISON_OPERATORS: [&'static str; 6] = [" > ", " < ", " >= ", " <= ", " = ", " != "];
174
175    pub fn consume(&mut self, expected: Token) -> Result<(), String> {
176        self.trace_token(&format!("Consuming expected {:?}", expected));
177        if std::mem::discriminant(&self.current_token) == std::mem::discriminant(&expected) {
178            // Track parentheses depth
179            self.update_paren_depth(&expected)?;
180
181            self.current_token = self.lexer.next_token();
182            Ok(())
183        } else {
184            // Provide better error messages for common cases
185            let error_msg = match (&expected, &self.current_token) {
186                (Token::RightParen, Token::Eof) if self.paren_depth > 0 => {
187                    format!(
188                        "Unclosed parenthesis - missing {} closing parenthes{}",
189                        self.paren_depth,
190                        if self.paren_depth == 1 { "is" } else { "es" }
191                    )
192                }
193                (Token::RightParen, _) if self.paren_depth > 0 => {
194                    format!(
195                        "Expected closing parenthesis but found {:?} (currently {} unclosed parenthes{})",
196                        self.current_token,
197                        self.paren_depth,
198                        if self.paren_depth == 1 { "is" } else { "es" }
199                    )
200                }
201                _ => format!("Expected {:?}, found {:?}", expected, self.current_token),
202            };
203            Err(error_msg)
204        }
205    }
206
207    pub fn advance(&mut self) {
208        // Track parentheses depth when advancing
209        match &self.current_token {
210            Token::LeftParen => self.paren_depth += 1,
211            Token::RightParen => {
212                self.paren_depth -= 1;
213                // Note: We don't check for < 0 here because advance() is used
214                // in contexts where we're not necessarily expecting a right paren
215            }
216            _ => {}
217        }
218        let old_token = self.current_token.clone();
219        self.current_token = self.lexer.next_token();
220        if self.debug_trace {
221            let indent = "  ".repeat(self.trace_depth);
222            eprintln!(
223                "{}  Advanced: {:?} → {:?}",
224                indent, old_token, self.current_token
225            );
226        }
227    }
228
229    fn push_paren_depth(&mut self) {
230        self.paren_depth_stack.push(self.paren_depth);
231        self.paren_depth = 0;
232    }
233
234    fn pop_paren_depth(&mut self) {
235        if let Some(depth) = self.paren_depth_stack.pop() {
236            // Ignore the internal depth - just restore the saved value
237            self.paren_depth = depth;
238        } else {
239        }
240    }
241
242    pub fn parse(&mut self) -> Result<SelectStatement, String> {
243        self.trace_enter("parse");
244
245        // Check for WITH clause at the beginning
246        let result = if matches!(self.current_token, Token::With) {
247            self.parse_with_clause()
248        } else {
249            self.parse_select_statement()
250        };
251
252        self.trace_exit("parse", &result);
253        result
254    }
255
256    fn parse_with_clause(&mut self) -> Result<SelectStatement, String> {
257        self.consume(Token::With)?;
258        let ctes = self.parse_cte_list()?;
259
260        // Parse the main SELECT statement - use inner version since we're already tracking parens
261        let mut main_query = self.parse_select_statement_inner()?;
262        main_query.ctes = ctes;
263
264        // Check for balanced parentheses at the end of parsing
265        self.check_balanced_parentheses()?;
266
267        Ok(main_query)
268    }
269
270    fn parse_with_clause_inner(&mut self) -> Result<SelectStatement, String> {
271        self.consume(Token::With)?;
272        let ctes = self.parse_cte_list()?;
273
274        // Parse the main SELECT statement (without parenthesis checking for subqueries)
275        let mut main_query = self.parse_select_statement_inner()?;
276        main_query.ctes = ctes;
277
278        Ok(main_query)
279    }
280
281    // Helper function to parse CTE list - eliminates duplication
282    fn parse_cte_list(&mut self) -> Result<Vec<CTE>, String> {
283        let mut ctes = Vec::new();
284
285        // Parse CTEs
286        loop {
287            // Check for WEB keyword for each CTE (can be different for each one)
288            let is_web = if matches!(&self.current_token, Token::Web) {
289                self.trace_token("Found WEB keyword for CTE");
290                self.advance();
291                true
292            } else {
293                false
294            };
295
296            // Parse CTE name
297            let name = match &self.current_token {
298                Token::Identifier(name) => name.clone(),
299                _ => {
300                    return Err(format!(
301                        "Expected CTE name after {}",
302                        if is_web { "WEB" } else { "WITH or comma" }
303                    ))
304                }
305            };
306            self.advance();
307
308            // Optional column list: WITH t(col1, col2) AS ...
309            let column_list = if matches!(self.current_token, Token::LeftParen) {
310                self.advance();
311                let cols = self.parse_identifier_list()?;
312                self.consume(Token::RightParen)?;
313                Some(cols)
314            } else {
315                None
316            };
317
318            // Expect AS
319            self.consume(Token::As)?;
320
321            let cte_type = if is_web {
322                // Expect opening parenthesis for WEB CTE
323                self.consume(Token::LeftParen)?;
324                // Parse WEB CTE specification using dedicated parser
325                let web_spec = WebCteParser::parse(self)?;
326                // Consume closing parenthesis for WEB CTE
327                self.consume(Token::RightParen)?;
328                CTEType::Web(web_spec)
329            } else {
330                // For standard CTEs, push depth BEFORE consuming opening paren
331                // This ensures the paren is counted in the inner context
332                self.push_paren_depth();
333                // Now consume opening parenthesis
334                self.consume(Token::LeftParen)?;
335                let query = self.parse_select_statement_inner()?;
336                // Expect closing parenthesis while still in CTE context
337                self.consume(Token::RightParen)?;
338                // Now pop to restore outer depth after consuming both parens
339                self.pop_paren_depth();
340                CTEType::Standard(query)
341            };
342
343            ctes.push(CTE {
344                name,
345                column_list,
346                cte_type,
347            });
348
349            // Check for more CTEs
350            if !matches!(self.current_token, Token::Comma) {
351                break;
352            }
353            self.advance();
354        }
355
356        Ok(ctes)
357    }
358
359    /// Helper function to parse an optional table alias (with or without AS keyword)
360    fn parse_optional_alias(&mut self) -> Result<Option<String>, String> {
361        if matches!(self.current_token, Token::As) {
362            self.advance();
363            match &self.current_token {
364                Token::Identifier(name) => {
365                    let alias = name.clone();
366                    self.advance();
367                    Ok(Some(alias))
368                }
369                _ => Err("Expected alias name after AS".to_string()),
370            }
371        } else if let Token::Identifier(name) = &self.current_token {
372            // AS is optional for table aliases
373            let alias = name.clone();
374            self.advance();
375            Ok(Some(alias))
376        } else {
377            Ok(None)
378        }
379    }
380
381    /// Helper function to check if an identifier is valid (quoted or regular)
382    fn is_valid_identifier(name: &str) -> bool {
383        if name.starts_with('"') && name.ends_with('"') {
384            // Quoted identifier - always valid
385            true
386        } else {
387            // Regular identifier - check if it's alphanumeric or underscore
388            name.chars().all(|c| c.is_alphanumeric() || c == '_')
389        }
390    }
391
392    /// Helper function to update parentheses depth tracking
393    fn update_paren_depth(&mut self, token: &Token) -> Result<(), String> {
394        match token {
395            Token::LeftParen => self.paren_depth += 1,
396            Token::RightParen => {
397                self.paren_depth -= 1;
398                // Check for extra closing parenthesis
399                if self.paren_depth < 0 {
400                    return Err(
401                        "Unexpected closing parenthesis - no matching opening parenthesis"
402                            .to_string(),
403                    );
404                }
405            }
406            _ => {}
407        }
408        Ok(())
409    }
410
411    /// Helper function to parse comma-separated argument list
412    fn parse_argument_list(&mut self) -> Result<Vec<SqlExpression>, String> {
413        let mut args = Vec::new();
414
415        if !matches!(self.current_token, Token::RightParen) {
416            loop {
417                args.push(self.parse_expression()?);
418
419                if matches!(self.current_token, Token::Comma) {
420                    self.advance();
421                } else {
422                    break;
423                }
424            }
425        }
426
427        Ok(args)
428    }
429
430    /// Helper function to check for balanced parentheses at the end of parsing
431    fn check_balanced_parentheses(&self) -> Result<(), String> {
432        if self.paren_depth > 0 {
433            Err(format!(
434                "Unclosed parenthesis - missing {} closing parenthes{}",
435                self.paren_depth,
436                if self.paren_depth == 1 { "is" } else { "es" }
437            ))
438        } else if self.paren_depth < 0 {
439            Err("Extra closing parenthesis found - no matching opening parenthesis".to_string())
440        } else {
441            Ok(())
442        }
443    }
444
445    fn parse_select_statement(&mut self) -> Result<SelectStatement, String> {
446        self.trace_enter("parse_select_statement");
447        let result = self.parse_select_statement_inner()?;
448
449        // Check for balanced parentheses at the end of parsing
450        self.check_balanced_parentheses()?;
451
452        Ok(result)
453    }
454
455    fn parse_select_statement_inner(&mut self) -> Result<SelectStatement, String> {
456        self.consume(Token::Select)?;
457
458        // Check for DISTINCT keyword
459        let distinct = if matches!(self.current_token, Token::Distinct) {
460            self.advance();
461            true
462        } else {
463            false
464        };
465
466        // Parse SELECT items (supports computed expressions)
467        let select_items = self.parse_select_items()?;
468
469        // Create legacy columns vector for backward compatibility
470        let columns = select_items
471            .iter()
472            .map(|item| match item {
473                SelectItem::Star => "*".to_string(),
474                SelectItem::Column(col_ref) => col_ref.name.clone(),
475                SelectItem::Expression { alias, .. } => alias.clone(),
476            })
477            .collect();
478
479        // Parse FROM clause - can be a table name, subquery, or table function
480        let (from_table, from_subquery, from_function, from_alias) =
481            if matches!(self.current_token, Token::From) {
482                self.advance();
483
484                // Check for table function like RANGE()
485                if let Token::Identifier(name) = &self.current_token.clone() {
486                    // Check if this is a table function by consulting the registry
487                    // We need to lookahead to see if there's a parenthesis to distinguish
488                    // between a function call and a table with the same name
489                    let has_paren = self.peek_token() == Some(Token::LeftParen);
490                    if self.debug_trace {
491                        eprintln!(
492                            "  Checking {} for table function, has_paren={}",
493                            name, has_paren
494                        );
495                    }
496
497                    // Check if it's a known table function or generator
498                    // In FROM clause context, prioritize generators over scalar functions
499                    let is_table_function = if has_paren {
500                        // First check generator registry (for FROM clause context)
501                        if self.debug_trace {
502                            eprintln!("  Checking generator registry for {}", name.to_uppercase());
503                        }
504                        if let Some(_gen) = self.generator_registry.get(&name.to_uppercase()) {
505                            if self.debug_trace {
506                                eprintln!("  Found {} in generator registry", name);
507                            }
508                            self.trace_token(&format!("Found generator: {}", name));
509                            true
510                        } else {
511                            // Then check if it's a table function in the function registry
512                            if let Some(func) = self.function_registry.get(&name.to_uppercase()) {
513                                let sig = func.signature();
514                                let is_table_fn = sig.category == FunctionCategory::TableFunction;
515                                if self.debug_trace {
516                                    eprintln!(
517                                        "  Found {} in function registry, is_table_function={}",
518                                        name, is_table_fn
519                                    );
520                                }
521                                if is_table_fn {
522                                    self.trace_token(&format!(
523                                        "Found table function in function registry: {}",
524                                        name
525                                    ));
526                                }
527                                is_table_fn
528                            } else {
529                                if self.debug_trace {
530                                    eprintln!("  {} not found in either registry", name);
531                                    self.trace_token(&format!(
532                                        "Not found as generator or table function: {}",
533                                        name
534                                    ));
535                                }
536                                false
537                            }
538                        }
539                    } else {
540                        if self.debug_trace {
541                            eprintln!("  No parenthesis after {}, treating as table", name);
542                        }
543                        false
544                    };
545
546                    if is_table_function {
547                        // Parse table function
548                        let function_name = name.clone();
549                        self.advance(); // Skip function name
550
551                        // Parse arguments
552                        self.consume(Token::LeftParen)?;
553                        let args = self.parse_argument_list()?;
554                        self.consume(Token::RightParen)?;
555
556                        // Optional alias
557                        let alias = if matches!(self.current_token, Token::As) {
558                            self.advance();
559                            match &self.current_token {
560                                Token::Identifier(name) => {
561                                    let alias = name.clone();
562                                    self.advance();
563                                    Some(alias)
564                                }
565                                _ => return Err("Expected alias name after AS".to_string()),
566                            }
567                        } else if let Token::Identifier(name) = &self.current_token {
568                            let alias = name.clone();
569                            self.advance();
570                            Some(alias)
571                        } else {
572                            None
573                        };
574
575                        (
576                            None,
577                            None,
578                            Some(TableFunction::Generator {
579                                name: function_name,
580                                args,
581                            }),
582                            alias,
583                        )
584                    } else {
585                        // Not a RANGE, SPLIT, or generator function, so it's a regular table name
586                        let table_name = name.clone();
587                        self.advance();
588
589                        // Check for optional alias
590                        let alias = self.parse_optional_alias()?;
591
592                        (Some(table_name), None, None, alias)
593                    }
594                } else if matches!(self.current_token, Token::LeftParen) {
595                    // Check for subquery: FROM (SELECT ...) or FROM (WITH ... SELECT ...)
596                    self.advance();
597
598                    // Parse the subquery - it might start with WITH
599                    let subquery = if matches!(self.current_token, Token::With) {
600                        self.parse_with_clause_inner()?
601                    } else {
602                        self.parse_select_statement_inner()?
603                    };
604
605                    self.consume(Token::RightParen)?;
606
607                    // Subqueries must have an alias
608                    let alias = if matches!(self.current_token, Token::As) {
609                        self.advance();
610                        match &self.current_token {
611                            Token::Identifier(name) => {
612                                let alias = name.clone();
613                                self.advance();
614                                alias
615                            }
616                            _ => return Err("Expected alias name after AS".to_string()),
617                        }
618                    } else {
619                        // AS is optional, but alias is required
620                        match &self.current_token {
621                            Token::Identifier(name) => {
622                                let alias = name.clone();
623                                self.advance();
624                                alias
625                            }
626                            _ => {
627                                return Err(
628                                    "Subquery in FROM must have an alias (e.g., AS t)".to_string()
629                                )
630                            }
631                        }
632                    };
633
634                    (None, Some(Box::new(subquery)), None, Some(alias))
635                } else {
636                    // Regular table name
637                    match &self.current_token {
638                        Token::Identifier(table) => {
639                            let table_name = table.clone();
640                            self.advance();
641
642                            // Check for optional alias
643                            let alias = self.parse_optional_alias()?;
644
645                            (Some(table_name), None, None, alias)
646                        }
647                        Token::QuotedIdentifier(table) => {
648                            // Handle quoted table names
649                            let table_name = table.clone();
650                            self.advance();
651
652                            // Check for optional alias
653                            let alias = self.parse_optional_alias()?;
654
655                            (Some(table_name), None, None, alias)
656                        }
657                        _ => return Err("Expected table name or subquery after FROM".to_string()),
658                    }
659                }
660            } else {
661                (None, None, None, None)
662            };
663
664        // Parse JOIN clauses
665        let mut joins = Vec::new();
666        while self.is_join_token() {
667            joins.push(self.parse_join_clause()?);
668        }
669
670        let where_clause = if matches!(self.current_token, Token::Where) {
671            self.advance();
672            Some(self.parse_where_clause()?)
673        } else {
674            None
675        };
676
677        let group_by = if matches!(self.current_token, Token::GroupBy) {
678            self.advance();
679            // Parse expressions instead of just identifiers for GROUP BY
680            // This allows GROUP BY TIME_BUCKET(...), CASE ..., etc.
681            Some(self.parse_expression_list()?)
682        } else {
683            None
684        };
685
686        // Parse HAVING clause (must come after GROUP BY)
687        let having = if matches!(self.current_token, Token::Having) {
688            if group_by.is_none() {
689                return Err("HAVING clause requires GROUP BY".to_string());
690            }
691            self.advance();
692            Some(self.parse_expression()?)
693        } else {
694            None
695        };
696
697        // Parse INTO clause (for temporary tables)
698        let into_table = if matches!(self.current_token, Token::Into) {
699            self.advance();
700            Some(self.parse_into_clause()?)
701        } else {
702            None
703        };
704
705        // Parse ORDER BY clause (comes after GROUP BY and HAVING)
706        let order_by = if matches!(self.current_token, Token::OrderBy) {
707            self.trace_token("Found OrderBy token");
708            self.advance();
709            Some(self.parse_order_by_list()?)
710        } else if let Token::Identifier(s) = &self.current_token {
711            // This shouldn't happen if the lexer properly tokenizes ORDER BY
712            // But keeping as fallback for compatibility
713            if Self::is_identifier_reserved(s) && s.to_uppercase() == "ORDER" {
714                self.trace_token("Warning: ORDER as identifier instead of OrderBy token");
715                self.advance(); // consume ORDER
716                if matches!(&self.current_token, Token::By) {
717                    self.advance(); // consume BY
718                    Some(self.parse_order_by_list()?)
719                } else {
720                    return Err("Expected BY after ORDER".to_string());
721                }
722            } else {
723                None
724            }
725        } else {
726            None
727        };
728
729        // Parse LIMIT clause
730        let limit = if matches!(self.current_token, Token::Limit) {
731            self.advance();
732            match &self.current_token {
733                Token::NumberLiteral(num) => {
734                    let limit_val = num
735                        .parse::<usize>()
736                        .map_err(|_| format!("Invalid LIMIT value: {num}"))?;
737                    self.advance();
738                    Some(limit_val)
739                }
740                _ => return Err("Expected number after LIMIT".to_string()),
741            }
742        } else {
743            None
744        };
745
746        // Parse OFFSET clause
747        let offset = if matches!(self.current_token, Token::Offset) {
748            self.advance();
749            match &self.current_token {
750                Token::NumberLiteral(num) => {
751                    let offset_val = num
752                        .parse::<usize>()
753                        .map_err(|_| format!("Invalid OFFSET value: {num}"))?;
754                    self.advance();
755                    Some(offset_val)
756                }
757                _ => return Err("Expected number after OFFSET".to_string()),
758            }
759        } else {
760            None
761        };
762
763        Ok(SelectStatement {
764            distinct,
765            columns,
766            select_items,
767            from_table,
768            from_subquery,
769            from_function,
770            from_alias,
771            joins,
772            where_clause,
773            order_by,
774            group_by,
775            having,
776            limit,
777            offset,
778            ctes: Vec::new(), // Will be populated by WITH clause parser
779            into_table,
780        })
781    }
782
783    /// Parse SELECT items that support computed expressions with aliases
784    fn parse_select_items(&mut self) -> Result<Vec<SelectItem>, String> {
785        let mut items = Vec::new();
786
787        loop {
788            // Check for * only at the beginning of a select item
789            // After a comma, * could be either SELECT * or part of multiplication
790            if matches!(self.current_token, Token::Star) {
791                // Determine if this is SELECT * or multiplication
792                // SELECT * is only valid:
793                // 1. As the first item in SELECT
794                // 2. Right after a comma (but not if followed by something that makes it multiplication)
795
796                // For now, treat Star as SELECT * only if we're at the start or just after a comma
797                // and the star is not immediately followed by something that would make it multiplication
798                items.push(SelectItem::Star);
799                self.advance();
800            } else {
801                // Parse expression or column
802                let expr = self.parse_comparison()?; // Use comparison to support IS NULL and other comparisons
803
804                // Check for AS alias
805                let alias = if matches!(self.current_token, Token::As) {
806                    self.advance();
807                    match &self.current_token {
808                        Token::Identifier(alias_name) => {
809                            let alias = alias_name.clone();
810                            self.advance();
811                            alias
812                        }
813                        Token::QuotedIdentifier(alias_name) => {
814                            let alias = alias_name.clone();
815                            self.advance();
816                            alias
817                        }
818                        _ => return Err("Expected alias name after AS".to_string()),
819                    }
820                } else {
821                    // Generate default alias based on expression
822                    match &expr {
823                        SqlExpression::Column(col_ref) => col_ref.name.clone(),
824                        _ => format!("expr_{}", items.len() + 1), // Default alias for computed expressions
825                    }
826                };
827
828                // Create SelectItem based on expression type
829                let item = match expr {
830                    SqlExpression::Column(col_ref) if alias == col_ref.name => {
831                        // Simple column reference without alias
832                        SelectItem::Column(col_ref)
833                    }
834                    _ => {
835                        // Computed expression or column with different alias
836                        SelectItem::Expression { expr, alias }
837                    }
838                };
839
840                items.push(item);
841            }
842
843            // Check for comma to continue
844            if matches!(self.current_token, Token::Comma) {
845                self.advance();
846            } else {
847                break;
848            }
849        }
850
851        Ok(items)
852    }
853
854    fn parse_identifier_list(&mut self) -> Result<Vec<String>, String> {
855        let mut identifiers = Vec::new();
856
857        loop {
858            match &self.current_token {
859                Token::Identifier(id) => {
860                    // Check if this is a reserved keyword that should stop identifier parsing
861                    if Self::is_identifier_reserved(id) {
862                        // Stop parsing identifiers if we hit a reserved keyword
863                        break;
864                    }
865                    identifiers.push(id.clone());
866                    self.advance();
867                }
868                Token::QuotedIdentifier(id) => {
869                    // Handle quoted identifiers like "Customer Id"
870                    identifiers.push(id.clone());
871                    self.advance();
872                }
873                _ => {
874                    // Stop parsing if we hit any other token type
875                    break;
876                }
877            }
878
879            if matches!(self.current_token, Token::Comma) {
880                self.advance();
881            } else {
882                break;
883            }
884        }
885
886        if identifiers.is_empty() {
887            return Err("Expected at least one identifier".to_string());
888        }
889
890        Ok(identifiers)
891    }
892
893    fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
894        let mut partition_by = Vec::new();
895        let mut order_by = Vec::new();
896
897        // Check for PARTITION BY
898        if matches!(self.current_token, Token::Partition) {
899            self.advance(); // consume PARTITION
900            if !matches!(self.current_token, Token::By) {
901                return Err("Expected BY after PARTITION".to_string());
902            }
903            self.advance(); // consume BY
904
905            // Parse partition columns
906            partition_by = self.parse_identifier_list()?;
907        }
908
909        // Check for ORDER BY
910        if matches!(self.current_token, Token::OrderBy) {
911            self.advance(); // consume ORDER BY (as single token)
912            order_by = self.parse_order_by_list()?;
913        } else if let Token::Identifier(s) = &self.current_token {
914            if Self::is_identifier_reserved(s) && s.to_uppercase() == "ORDER" {
915                // Handle ORDER BY as two tokens
916                self.advance(); // consume ORDER
917                if !matches!(self.current_token, Token::By) {
918                    return Err("Expected BY after ORDER".to_string());
919                }
920                self.advance(); // consume BY
921                order_by = self.parse_order_by_list()?;
922            }
923        }
924
925        // Parse optional window frame (ROWS/RANGE BETWEEN ... AND ...)
926        let frame = self.parse_window_frame()?;
927
928        Ok(WindowSpec {
929            partition_by,
930            order_by,
931            frame,
932        })
933    }
934
935    fn parse_order_by_list(&mut self) -> Result<Vec<OrderByColumn>, String> {
936        let mut order_columns = Vec::new();
937
938        loop {
939            let column = match &self.current_token {
940                Token::Identifier(id) => {
941                    let col = id.clone();
942                    self.advance();
943
944                    // Check for qualified column name (table.column)
945                    if matches!(self.current_token, Token::Dot) {
946                        self.advance();
947                        match &self.current_token {
948                            Token::Identifier(col_name) => {
949                                let mut qualified = col;
950                                qualified.push('.');
951                                qualified.push_str(col_name);
952                                self.advance();
953                                qualified
954                            }
955                            _ => return Err("Expected column name after '.'".to_string()),
956                        }
957                    } else {
958                        col
959                    }
960                }
961                Token::QuotedIdentifier(id) => {
962                    let col = id.clone();
963                    self.advance();
964                    col
965                }
966                Token::NumberLiteral(num) if self.columns.iter().any(|col| col == num) => {
967                    // Support numeric column names like "202204"
968                    let col = num.clone();
969                    self.advance();
970                    col
971                }
972                // Handle window keywords that can be column names
973                Token::Row => {
974                    self.advance();
975                    "row".to_string()
976                }
977                Token::Rows => {
978                    self.advance();
979                    "rows".to_string()
980                }
981                Token::Range => {
982                    self.advance();
983                    "range".to_string()
984                }
985                _ => return Err("Expected column name in ORDER BY".to_string()),
986            };
987
988            // Check for ASC/DESC
989            let direction = match &self.current_token {
990                Token::Asc => {
991                    self.advance();
992                    SortDirection::Asc
993                }
994                Token::Desc => {
995                    self.advance();
996                    SortDirection::Desc
997                }
998                _ => SortDirection::Asc, // Default to ASC if not specified
999            };
1000
1001            order_columns.push(OrderByColumn { column, direction });
1002
1003            if matches!(self.current_token, Token::Comma) {
1004                self.advance();
1005            } else {
1006                break;
1007            }
1008        }
1009
1010        Ok(order_columns)
1011    }
1012
1013    /// Parse INTO clause for temporary tables
1014    /// Syntax: INTO #table_name
1015    fn parse_into_clause(&mut self) -> Result<IntoTable, String> {
1016        // Expect an identifier starting with #
1017        let name = match &self.current_token {
1018            Token::Identifier(id) if id.starts_with('#') => {
1019                let table_name = id.clone();
1020                self.advance();
1021                table_name
1022            }
1023            Token::Identifier(id) => {
1024                return Err(format!(
1025                    "Temporary table name must start with #, got: {}",
1026                    id
1027                ));
1028            }
1029            _ => {
1030                return Err(
1031                    "Expected temporary table name (starting with #) after INTO".to_string()
1032                );
1033            }
1034        };
1035
1036        Ok(IntoTable { name })
1037    }
1038
1039    fn parse_window_frame(&mut self) -> Result<Option<WindowFrame>, String> {
1040        // Check for ROWS or RANGE keyword
1041        let unit = match &self.current_token {
1042            Token::Rows => {
1043                self.advance();
1044                FrameUnit::Rows
1045            }
1046            Token::Identifier(id) if id.to_uppercase() == "RANGE" => {
1047                // RANGE as window frame unit
1048                self.advance();
1049                FrameUnit::Range
1050            }
1051            _ => return Ok(None), // No window frame specified
1052        };
1053
1054        // Check for BETWEEN or just a single bound
1055        let (start, end) = if let Token::Between = &self.current_token {
1056            self.advance(); // consume BETWEEN
1057                            // Parse start bound
1058            let start = self.parse_frame_bound()?;
1059
1060            // Expect AND
1061            if !matches!(&self.current_token, Token::And) {
1062                return Err("Expected AND after window frame start bound".to_string());
1063            }
1064            self.advance();
1065
1066            // Parse end bound
1067            let end = self.parse_frame_bound()?;
1068            (start, Some(end))
1069        } else {
1070            // Single bound (e.g., "ROWS 5 PRECEDING")
1071            let bound = self.parse_frame_bound()?;
1072            (bound, None)
1073        };
1074
1075        Ok(Some(WindowFrame { unit, start, end }))
1076    }
1077
1078    fn parse_frame_bound(&mut self) -> Result<FrameBound, String> {
1079        match &self.current_token {
1080            Token::Unbounded => {
1081                self.advance();
1082                match &self.current_token {
1083                    Token::Preceding => {
1084                        self.advance();
1085                        Ok(FrameBound::UnboundedPreceding)
1086                    }
1087                    Token::Following => {
1088                        self.advance();
1089                        Ok(FrameBound::UnboundedFollowing)
1090                    }
1091                    _ => Err("Expected PRECEDING or FOLLOWING after UNBOUNDED".to_string()),
1092                }
1093            }
1094            Token::Current => {
1095                self.advance();
1096                if matches!(&self.current_token, Token::Row) {
1097                    self.advance();
1098                    return Ok(FrameBound::CurrentRow);
1099                }
1100                Err("Expected ROW after CURRENT".to_string())
1101            }
1102            Token::NumberLiteral(num) => {
1103                let n: i64 = num
1104                    .parse()
1105                    .map_err(|_| "Invalid number in window frame".to_string())?;
1106                self.advance();
1107                match &self.current_token {
1108                    Token::Preceding => {
1109                        self.advance();
1110                        Ok(FrameBound::Preceding(n))
1111                    }
1112                    Token::Following => {
1113                        self.advance();
1114                        Ok(FrameBound::Following(n))
1115                    }
1116                    _ => Err("Expected PRECEDING or FOLLOWING after number".to_string()),
1117                }
1118            }
1119            _ => Err("Invalid window frame bound".to_string()),
1120        }
1121    }
1122
1123    fn parse_where_clause(&mut self) -> Result<WhereClause, String> {
1124        // Parse the entire WHERE clause as a single expression tree
1125        // The logical operators (AND/OR) are now handled within parse_expression
1126        let expr = self.parse_expression()?;
1127
1128        // Check for unexpected closing parenthesis
1129        if matches!(self.current_token, Token::RightParen) && self.paren_depth <= 0 {
1130            return Err(
1131                "Unexpected closing parenthesis - no matching opening parenthesis".to_string(),
1132            );
1133        }
1134
1135        // Create a single condition with the entire expression
1136        let conditions = vec![Condition {
1137            expr,
1138            connector: None,
1139        }];
1140
1141        Ok(WhereClause { conditions })
1142    }
1143
1144    fn parse_expression(&mut self) -> Result<SqlExpression, String> {
1145        self.trace_enter("parse_expression");
1146        // Start with logical OR as the lowest precedence operator
1147        // The hierarchy is: OR -> AND -> comparison -> additive -> multiplicative -> primary
1148        let mut left = self.parse_logical_or()?;
1149
1150        // Handle IN operator (not preceded by NOT)
1151        // This uses the modular comparison module
1152        left = parse_in_operator(self, left)?;
1153
1154        let result = Ok(left);
1155        self.trace_exit("parse_expression", &result);
1156        result
1157    }
1158
1159    fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1160        // Use the new modular comparison expression parser
1161        parse_comparison_expr(self)
1162    }
1163
1164    fn parse_additive(&mut self) -> Result<SqlExpression, String> {
1165        // Use the new modular arithmetic expression parser
1166        parse_additive_expr(self)
1167    }
1168
1169    fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
1170        // Use the new modular arithmetic expression parser
1171        parse_multiplicative_expr(self)
1172    }
1173
1174    fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1175        // Use the new modular logical expression parser
1176        parse_logical_or_expr(self)
1177    }
1178
1179    fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
1180        // Use the new modular logical expression parser
1181        parse_logical_and_expr(self)
1182    }
1183
1184    fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1185        // Use the new modular CASE expression parser
1186        parse_case_expr(self)
1187    }
1188
1189    fn parse_primary(&mut self) -> Result<SqlExpression, String> {
1190        // Use the new modular primary expression parser
1191        // Clone the necessary data to avoid borrowing issues
1192        let columns = self.columns.clone();
1193        let in_method_args = self.in_method_args;
1194        let ctx = PrimaryExpressionContext {
1195            columns: &columns,
1196            in_method_args,
1197        };
1198        parse_primary_expr(self, &ctx)
1199    }
1200
1201    // Keep the old implementation temporarily for reference (will be removed)
1202    fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
1203        // Set flag to indicate we're parsing method arguments
1204        self.in_method_args = true;
1205
1206        let args = self.parse_argument_list()?;
1207
1208        // Clear the flag
1209        self.in_method_args = false;
1210
1211        Ok(args)
1212    }
1213
1214    fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1215        let mut args = Vec::new();
1216        let mut has_distinct = false;
1217
1218        if !matches!(self.current_token, Token::RightParen) {
1219            // Check if first argument starts with DISTINCT
1220            if matches!(self.current_token, Token::Distinct) {
1221                self.advance(); // consume DISTINCT
1222                has_distinct = true;
1223            }
1224
1225            // Parse the expression (either after DISTINCT or directly)
1226            args.push(self.parse_additive()?);
1227
1228            // Parse any remaining arguments (DISTINCT only applies to first arg for aggregates)
1229            while matches!(self.current_token, Token::Comma) {
1230                self.advance();
1231                args.push(self.parse_additive()?);
1232            }
1233        }
1234
1235        Ok((args, has_distinct))
1236    }
1237
1238    fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1239        let mut expressions = Vec::new();
1240
1241        loop {
1242            expressions.push(self.parse_expression()?);
1243
1244            if matches!(self.current_token, Token::Comma) {
1245                self.advance();
1246            } else {
1247                break;
1248            }
1249        }
1250
1251        Ok(expressions)
1252    }
1253
1254    #[must_use]
1255    pub fn get_position(&self) -> usize {
1256        self.lexer.get_position()
1257    }
1258
1259    // Check if current token is a JOIN-related token
1260    fn is_join_token(&self) -> bool {
1261        matches!(
1262            self.current_token,
1263            Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
1264        )
1265    }
1266
1267    // Parse a JOIN clause
1268    fn parse_join_clause(&mut self) -> Result<JoinClause, String> {
1269        // Determine join type
1270        let join_type = match &self.current_token {
1271            Token::Join => {
1272                self.advance();
1273                JoinType::Inner // Default JOIN is INNER JOIN
1274            }
1275            Token::Inner => {
1276                self.advance();
1277                if !matches!(self.current_token, Token::Join) {
1278                    return Err("Expected JOIN after INNER".to_string());
1279                }
1280                self.advance();
1281                JoinType::Inner
1282            }
1283            Token::Left => {
1284                self.advance();
1285                // Handle optional OUTER keyword
1286                if matches!(self.current_token, Token::Outer) {
1287                    self.advance();
1288                }
1289                if !matches!(self.current_token, Token::Join) {
1290                    return Err("Expected JOIN after LEFT".to_string());
1291                }
1292                self.advance();
1293                JoinType::Left
1294            }
1295            Token::Right => {
1296                self.advance();
1297                // Handle optional OUTER keyword
1298                if matches!(self.current_token, Token::Outer) {
1299                    self.advance();
1300                }
1301                if !matches!(self.current_token, Token::Join) {
1302                    return Err("Expected JOIN after RIGHT".to_string());
1303                }
1304                self.advance();
1305                JoinType::Right
1306            }
1307            Token::Full => {
1308                self.advance();
1309                // Handle optional OUTER keyword
1310                if matches!(self.current_token, Token::Outer) {
1311                    self.advance();
1312                }
1313                if !matches!(self.current_token, Token::Join) {
1314                    return Err("Expected JOIN after FULL".to_string());
1315                }
1316                self.advance();
1317                JoinType::Full
1318            }
1319            Token::Cross => {
1320                self.advance();
1321                if !matches!(self.current_token, Token::Join) {
1322                    return Err("Expected JOIN after CROSS".to_string());
1323                }
1324                self.advance();
1325                JoinType::Cross
1326            }
1327            _ => return Err("Expected JOIN keyword".to_string()),
1328        };
1329
1330        // Parse the table being joined
1331        let (table, alias) = self.parse_join_table_source()?;
1332
1333        // Parse ON condition (required for all joins except CROSS JOIN)
1334        let condition = if join_type == JoinType::Cross {
1335            // CROSS JOIN doesn't have ON condition - create empty condition
1336            JoinCondition { conditions: vec![] }
1337        } else {
1338            if !matches!(self.current_token, Token::On) {
1339                return Err("Expected ON keyword after JOIN table".to_string());
1340            }
1341            self.advance();
1342            self.parse_join_condition()?
1343        };
1344
1345        Ok(JoinClause {
1346            join_type,
1347            table,
1348            alias,
1349            condition,
1350        })
1351    }
1352
1353    fn parse_join_table_source(&mut self) -> Result<(TableSource, Option<String>), String> {
1354        let table = match &self.current_token {
1355            Token::Identifier(name) => {
1356                let table_name = name.clone();
1357                self.advance();
1358                TableSource::Table(table_name)
1359            }
1360            Token::LeftParen => {
1361                // Subquery as table source
1362                self.advance();
1363                let subquery = self.parse_select_statement_inner()?;
1364                if !matches!(self.current_token, Token::RightParen) {
1365                    return Err("Expected ')' after subquery".to_string());
1366                }
1367                self.advance();
1368
1369                // Subqueries must have an alias
1370                let alias = match &self.current_token {
1371                    Token::Identifier(alias_name) => {
1372                        let alias = alias_name.clone();
1373                        self.advance();
1374                        alias
1375                    }
1376                    Token::As => {
1377                        self.advance();
1378                        match &self.current_token {
1379                            Token::Identifier(alias_name) => {
1380                                let alias = alias_name.clone();
1381                                self.advance();
1382                                alias
1383                            }
1384                            _ => return Err("Expected alias after AS keyword".to_string()),
1385                        }
1386                    }
1387                    _ => return Err("Subqueries must have an alias".to_string()),
1388                };
1389
1390                return Ok((
1391                    TableSource::DerivedTable {
1392                        query: Box::new(subquery),
1393                        alias: alias.clone(),
1394                    },
1395                    Some(alias),
1396                ));
1397            }
1398            _ => return Err("Expected table name or subquery in JOIN clause".to_string()),
1399        };
1400
1401        // Check for optional alias
1402        let alias = match &self.current_token {
1403            Token::Identifier(alias_name) => {
1404                let alias = alias_name.clone();
1405                self.advance();
1406                Some(alias)
1407            }
1408            Token::As => {
1409                self.advance();
1410                match &self.current_token {
1411                    Token::Identifier(alias_name) => {
1412                        let alias = alias_name.clone();
1413                        self.advance();
1414                        Some(alias)
1415                    }
1416                    _ => return Err("Expected alias after AS keyword".to_string()),
1417                }
1418            }
1419            _ => None,
1420        };
1421
1422        Ok((table, alias))
1423    }
1424
1425    fn parse_join_condition(&mut self) -> Result<JoinCondition, String> {
1426        let mut conditions = Vec::new();
1427
1428        // Parse first condition
1429        conditions.push(self.parse_single_join_condition()?);
1430
1431        // Parse additional conditions connected by AND
1432        while matches!(self.current_token, Token::And) {
1433            self.advance(); // consume AND
1434            conditions.push(self.parse_single_join_condition()?);
1435        }
1436
1437        Ok(JoinCondition { conditions })
1438    }
1439
1440    fn parse_single_join_condition(&mut self) -> Result<SingleJoinCondition, String> {
1441        // Parse left column (can include table prefix)
1442        let left_column = self.parse_column_reference()?;
1443
1444        // Parse operator
1445        let operator = match &self.current_token {
1446            Token::Equal => JoinOperator::Equal,
1447            Token::NotEqual => JoinOperator::NotEqual,
1448            Token::LessThan => JoinOperator::LessThan,
1449            Token::LessThanOrEqual => JoinOperator::LessThanOrEqual,
1450            Token::GreaterThan => JoinOperator::GreaterThan,
1451            Token::GreaterThanOrEqual => JoinOperator::GreaterThanOrEqual,
1452            _ => return Err("Expected comparison operator in JOIN condition".to_string()),
1453        };
1454        self.advance();
1455
1456        // Parse right column (can include table prefix)
1457        let right_column = self.parse_column_reference()?;
1458
1459        Ok(SingleJoinCondition {
1460            left_column,
1461            operator,
1462            right_column,
1463        })
1464    }
1465
1466    fn parse_column_reference(&mut self) -> Result<String, String> {
1467        match &self.current_token {
1468            Token::Identifier(name) => {
1469                let mut column_ref = name.clone();
1470                self.advance();
1471
1472                // Check for table.column notation
1473                if matches!(self.current_token, Token::Dot) {
1474                    self.advance();
1475                    match &self.current_token {
1476                        Token::Identifier(col_name) => {
1477                            column_ref.push('.');
1478                            column_ref.push_str(col_name);
1479                            self.advance();
1480                        }
1481                        _ => return Err("Expected column name after '.'".to_string()),
1482                    }
1483                }
1484
1485                Ok(column_ref)
1486            }
1487            _ => Err("Expected column reference".to_string()),
1488        }
1489    }
1490}
1491
1492// Context detection for cursor position
1493#[derive(Debug, Clone)]
1494pub enum CursorContext {
1495    SelectClause,
1496    FromClause,
1497    WhereClause,
1498    OrderByClause,
1499    AfterColumn(String),
1500    AfterLogicalOp(LogicalOp),
1501    AfterComparisonOp(String, String), // column_name, operator
1502    InMethodCall(String, String),      // object, method
1503    InExpression,
1504    Unknown,
1505}
1506
1507/// Safe UTF-8 string slicing that ensures we don't slice in the middle of a character
1508fn safe_slice_to(s: &str, pos: usize) -> &str {
1509    if pos >= s.len() {
1510        return s;
1511    }
1512
1513    // Find the nearest valid character boundary at or before pos
1514    let mut safe_pos = pos;
1515    while safe_pos > 0 && !s.is_char_boundary(safe_pos) {
1516        safe_pos -= 1;
1517    }
1518
1519    &s[..safe_pos]
1520}
1521
1522/// Safe UTF-8 string slicing from a position to the end
1523fn safe_slice_from(s: &str, pos: usize) -> &str {
1524    if pos >= s.len() {
1525        return "";
1526    }
1527
1528    // Find the nearest valid character boundary at or after pos
1529    let mut safe_pos = pos;
1530    while safe_pos < s.len() && !s.is_char_boundary(safe_pos) {
1531        safe_pos += 1;
1532    }
1533
1534    &s[safe_pos..]
1535}
1536
1537#[must_use]
1538pub fn detect_cursor_context(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1539    let truncated = safe_slice_to(query, cursor_pos);
1540    let mut parser = Parser::new(truncated);
1541
1542    // Try to parse as much as possible
1543    if let Ok(stmt) = parser.parse() {
1544        let (ctx, partial) = analyze_statement(&stmt, truncated, cursor_pos);
1545        #[cfg(test)]
1546        println!("analyze_statement returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1547        (ctx, partial)
1548    } else {
1549        // Partial parse - analyze what we have
1550        let (ctx, partial) = analyze_partial(truncated, cursor_pos);
1551        #[cfg(test)]
1552        println!("analyze_partial returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1553        (ctx, partial)
1554    }
1555}
1556
1557#[must_use]
1558pub fn tokenize_query(query: &str) -> Vec<String> {
1559    let mut lexer = Lexer::new(query);
1560    let tokens = lexer.tokenize_all();
1561    tokens.iter().map(|t| format!("{t:?}")).collect()
1562}
1563
1564#[must_use]
1565/// Helper function to find the start of a quoted string searching backwards
1566fn find_quote_start(bytes: &[u8], mut pos: usize) -> Option<usize> {
1567    // Skip the closing quote and search backwards
1568    if pos > 0 {
1569        pos -= 1;
1570        while pos > 0 {
1571            if bytes[pos] == b'"' {
1572                // Check if it's not an escaped quote
1573                if pos == 0 || bytes[pos - 1] != b'\\' {
1574                    return Some(pos);
1575                }
1576            }
1577            pos -= 1;
1578        }
1579        // Check position 0 separately
1580        if bytes[0] == b'"' {
1581            return Some(0);
1582        }
1583    }
1584    None
1585}
1586
1587/// Helper function to handle method call context after validation
1588fn handle_method_call_context(col_name: &str, after_dot: &str) -> (CursorContext, Option<String>) {
1589    // Check if there's a partial method name after the dot
1590    let partial_method = if after_dot.is_empty() {
1591        None
1592    } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1593        Some(after_dot.to_string())
1594    } else {
1595        None
1596    };
1597
1598    // For AfterColumn context, strip quotes if present for consistency
1599    let col_name_for_context =
1600        if col_name.starts_with('"') && col_name.ends_with('"') && col_name.len() > 2 {
1601            col_name[1..col_name.len() - 1].to_string()
1602        } else {
1603            col_name.to_string()
1604        };
1605
1606    (
1607        CursorContext::AfterColumn(col_name_for_context),
1608        partial_method,
1609    )
1610}
1611
1612/// Helper function to check if we're after a comparison operator
1613fn check_after_comparison_operator(query: &str) -> Option<(CursorContext, Option<String>)> {
1614    for op in &Parser::COMPARISON_OPERATORS {
1615        if let Some(op_pos) = query.rfind(op) {
1616            let before_op = safe_slice_to(query, op_pos);
1617            let after_op_start = op_pos + op.len();
1618            let after_op = if after_op_start < query.len() {
1619                &query[after_op_start..]
1620            } else {
1621                ""
1622            };
1623
1624            // Check if we have a column name before the operator
1625            if let Some(col_name) = before_op.split_whitespace().last() {
1626                if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1627                    // Check if we're at or near the end of the query
1628                    let after_op_trimmed = after_op.trim();
1629                    if after_op_trimmed.is_empty()
1630                        || (after_op_trimmed
1631                            .chars()
1632                            .all(|c| c.is_alphanumeric() || c == '_')
1633                            && !after_op_trimmed.contains('('))
1634                    {
1635                        let partial = if after_op_trimmed.is_empty() {
1636                            None
1637                        } else {
1638                            Some(after_op_trimmed.to_string())
1639                        };
1640                        return Some((
1641                            CursorContext::AfterComparisonOp(
1642                                col_name.to_string(),
1643                                op.trim().to_string(),
1644                            ),
1645                            partial,
1646                        ));
1647                    }
1648                }
1649            }
1650        }
1651    }
1652    None
1653}
1654
1655fn analyze_statement(
1656    stmt: &SelectStatement,
1657    query: &str,
1658    _cursor_pos: usize,
1659) -> (CursorContext, Option<String>) {
1660    // First check for method call context (e.g., "columnName." or "columnName.Con")
1661    let trimmed = query.trim();
1662
1663    // Check if we're after a comparison operator (e.g., "createdDate > ")
1664    if let Some(result) = check_after_comparison_operator(query) {
1665        return result;
1666    }
1667
1668    // First check if we're after AND/OR - this takes precedence
1669    // Helper function to check if string ends with a logical operator
1670    let ends_with_logical_op = |s: &str| -> bool {
1671        let s_upper = s.to_uppercase();
1672        s_upper.ends_with(" AND") || s_upper.ends_with(" OR")
1673    };
1674
1675    if ends_with_logical_op(trimmed) {
1676        // Don't check for method context if we're clearly after a logical operator
1677    } else {
1678        // Look for the last dot in the query
1679        if let Some(dot_pos) = trimmed.rfind('.') {
1680            // Check if we're after a column name and dot
1681            let before_dot = safe_slice_to(trimmed, dot_pos);
1682            let after_dot_start = dot_pos + 1;
1683            let after_dot = if after_dot_start < trimmed.len() {
1684                &trimmed[after_dot_start..]
1685            } else {
1686                ""
1687            };
1688
1689            // Check if the part after dot looks like an incomplete method call
1690            // (not a complete method call like "Contains(...)")
1691            if !after_dot.contains('(') {
1692                // Try to extract the column name - could be quoted or regular
1693                let col_name = if before_dot.ends_with('"') {
1694                    // Handle quoted identifier - search backwards for matching opening quote
1695                    let bytes = before_dot.as_bytes();
1696                    let pos = before_dot.len() - 1; // Position of closing quote
1697
1698                    find_quote_start(bytes, pos).map(|start| safe_slice_from(before_dot, start))
1699                } else {
1700                    // Regular identifier - get the last word, handling parentheses
1701                    // Strip all leading parentheses
1702                    before_dot
1703                        .split_whitespace()
1704                        .last()
1705                        .map(|word| word.trim_start_matches('('))
1706                };
1707
1708                if let Some(col_name) = col_name {
1709                    // For quoted identifiers, keep the quotes, for regular identifiers check validity
1710                    let is_valid = Parser::is_valid_identifier(col_name);
1711
1712                    if is_valid {
1713                        return handle_method_call_context(col_name, after_dot);
1714                    }
1715                }
1716            }
1717        }
1718    }
1719
1720    // Check if we're in WHERE clause
1721    if let Some(where_clause) = &stmt.where_clause {
1722        // Check if query ends with AND/OR (with or without trailing space/partial)
1723        let trimmed_upper = trimmed.to_uppercase();
1724        if trimmed_upper.ends_with(" AND") || trimmed_upper.ends_with(" OR") {
1725            let op = if trimmed_upper.ends_with(" AND") {
1726                LogicalOp::And
1727            } else {
1728                LogicalOp::Or
1729            };
1730            return (CursorContext::AfterLogicalOp(op), None);
1731        }
1732
1733        // Check if we have AND/OR followed by a partial word
1734        let query_upper = query.to_uppercase();
1735        if let Some(and_pos) = query_upper.rfind(" AND ") {
1736            let after_and = safe_slice_from(query, and_pos + 5);
1737            let partial = extract_partial_at_end(after_and);
1738            if partial.is_some() {
1739                return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1740            }
1741        }
1742
1743        if let Some(or_pos) = query_upper.rfind(" OR ") {
1744            let after_or = safe_slice_from(query, or_pos + 4);
1745            let partial = extract_partial_at_end(after_or);
1746            if partial.is_some() {
1747                return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1748            }
1749        }
1750
1751        if let Some(last_condition) = where_clause.conditions.last() {
1752            if let Some(connector) = &last_condition.connector {
1753                // We're after AND/OR
1754                return (
1755                    CursorContext::AfterLogicalOp(connector.clone()),
1756                    extract_partial_at_end(query),
1757                );
1758            }
1759        }
1760        // We're in WHERE clause but not after AND/OR
1761        return (CursorContext::WhereClause, extract_partial_at_end(query));
1762    }
1763
1764    // Check if we're after ORDER BY
1765    let query_upper = query.to_uppercase();
1766    if query_upper.ends_with(" ORDER BY") {
1767        return (CursorContext::OrderByClause, None);
1768    }
1769
1770    // Check other contexts based on what's in the statement
1771    if stmt.order_by.is_some() {
1772        return (CursorContext::OrderByClause, extract_partial_at_end(query));
1773    }
1774
1775    if stmt.from_table.is_some() && stmt.where_clause.is_none() && stmt.order_by.is_none() {
1776        return (CursorContext::FromClause, extract_partial_at_end(query));
1777    }
1778
1779    if !stmt.columns.is_empty() && stmt.from_table.is_none() {
1780        return (CursorContext::SelectClause, extract_partial_at_end(query));
1781    }
1782
1783    (CursorContext::Unknown, None)
1784}
1785
1786/// Helper function to find the last occurrence of a token type in the token stream
1787fn find_last_token(tokens: &[(usize, usize, Token)], target: &Token) -> Option<usize> {
1788    tokens
1789        .iter()
1790        .rposition(|(_, _, t)| t == target)
1791        .map(|idx| tokens[idx].0)
1792}
1793
1794/// Helper function to find the last occurrence of any matching token
1795fn find_last_matching_token<F>(
1796    tokens: &[(usize, usize, Token)],
1797    predicate: F,
1798) -> Option<(usize, &Token)>
1799where
1800    F: Fn(&Token) -> bool,
1801{
1802    tokens
1803        .iter()
1804        .rposition(|(_, _, t)| predicate(t))
1805        .map(|idx| (tokens[idx].0, &tokens[idx].2))
1806}
1807
1808/// Helper function to check if we're in a specific clause based on tokens
1809fn is_in_clause(
1810    tokens: &[(usize, usize, Token)],
1811    clause_token: Token,
1812    exclude_tokens: &[Token],
1813) -> bool {
1814    // Find the last occurrence of the clause token
1815    if let Some(clause_pos) = find_last_token(tokens, &clause_token) {
1816        // Check if any exclude tokens appear after it
1817        for (pos, _, token) in tokens.iter() {
1818            if *pos > clause_pos && exclude_tokens.contains(token) {
1819                return false;
1820            }
1821        }
1822        return true;
1823    }
1824    false
1825}
1826
1827fn analyze_partial(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1828    // Tokenize the query up to cursor position
1829    let mut lexer = Lexer::new(query);
1830    let tokens = lexer.tokenize_all_with_positions();
1831
1832    let trimmed = query.trim();
1833
1834    #[cfg(test)]
1835    {
1836        if trimmed.contains("\"Last Name\"") {
1837            eprintln!("DEBUG analyze_partial: query='{query}', trimmed='{trimmed}'");
1838        }
1839    }
1840
1841    // Check if we're after a comparison operator (e.g., "createdDate > ")
1842    if let Some(result) = check_after_comparison_operator(query) {
1843        return result;
1844    }
1845
1846    // Look for the last dot in the query (method call context) - check this FIRST
1847    // before AND/OR detection to properly handle cases like "AND (Country."
1848    if let Some(dot_pos) = trimmed.rfind('.') {
1849        #[cfg(test)]
1850        {
1851            if trimmed.contains("\"Last Name\"") {
1852                eprintln!("DEBUG: Found dot at position {dot_pos}");
1853            }
1854        }
1855        // Check if we're after a column name and dot
1856        let before_dot = &trimmed[..dot_pos];
1857        let after_dot = &trimmed[dot_pos + 1..];
1858
1859        // Check if the part after dot looks like an incomplete method call
1860        // (not a complete method call like "Contains(...)")
1861        if !after_dot.contains('(') {
1862            // Try to extract the column name before the dot
1863            // It could be a quoted identifier like "Last Name" or a regular identifier
1864            let col_name = if before_dot.ends_with('"') {
1865                // Handle quoted identifier - search backwards for matching opening quote
1866                let bytes = before_dot.as_bytes();
1867                let pos = before_dot.len() - 1; // Position of closing quote
1868
1869                #[cfg(test)]
1870                {
1871                    if trimmed.contains("\"Last Name\"") {
1872                        eprintln!("DEBUG: before_dot='{before_dot}', looking for opening quote");
1873                    }
1874                }
1875
1876                let found_start = find_quote_start(bytes, pos);
1877
1878                if let Some(start) = found_start {
1879                    // Extract the full quoted identifier including quotes
1880                    let result = safe_slice_from(before_dot, start);
1881                    #[cfg(test)]
1882                    {
1883                        if trimmed.contains("\"Last Name\"") {
1884                            eprintln!("DEBUG: Extracted quoted identifier: '{result}'");
1885                        }
1886                    }
1887                    Some(result)
1888                } else {
1889                    #[cfg(test)]
1890                    {
1891                        if trimmed.contains("\"Last Name\"") {
1892                            eprintln!("DEBUG: No opening quote found!");
1893                        }
1894                    }
1895                    None
1896                }
1897            } else {
1898                // Regular identifier - get the last word, handling parentheses
1899                // Strip all leading parentheses
1900                before_dot
1901                    .split_whitespace()
1902                    .last()
1903                    .map(|word| word.trim_start_matches('('))
1904            };
1905
1906            if let Some(col_name) = col_name {
1907                #[cfg(test)]
1908                {
1909                    if trimmed.contains("\"Last Name\"") {
1910                        eprintln!("DEBUG: col_name = '{col_name}'");
1911                    }
1912                }
1913
1914                // For quoted identifiers, keep the quotes, for regular identifiers check validity
1915                let is_valid = Parser::is_valid_identifier(col_name);
1916
1917                #[cfg(test)]
1918                {
1919                    if trimmed.contains("\"Last Name\"") {
1920                        eprintln!("DEBUG: is_valid = {is_valid}");
1921                    }
1922                }
1923
1924                if is_valid {
1925                    return handle_method_call_context(col_name, after_dot);
1926                }
1927            }
1928        }
1929    }
1930
1931    // Check if we're after AND/OR using tokens - but only after checking for method calls
1932    if let Some((pos, token)) =
1933        find_last_matching_token(&tokens, |t| matches!(t, Token::And | Token::Or))
1934    {
1935        // Check if cursor is after the logical operator
1936        let token_end_pos = if matches!(token, Token::And) {
1937            pos + 3 // "AND" is 3 characters
1938        } else {
1939            pos + 2 // "OR" is 2 characters
1940        };
1941
1942        if cursor_pos > token_end_pos {
1943            // Extract any partial word after the operator
1944            let after_op = safe_slice_from(query, token_end_pos + 1); // +1 for the space
1945            let partial = extract_partial_at_end(after_op);
1946            let op = if matches!(token, Token::And) {
1947                LogicalOp::And
1948            } else {
1949                LogicalOp::Or
1950            };
1951            return (CursorContext::AfterLogicalOp(op), partial);
1952        }
1953    }
1954
1955    // Check if the last token is AND or OR (handles case where it's at the very end)
1956    if let Some((_, _, last_token)) = tokens.last() {
1957        if matches!(last_token, Token::And | Token::Or) {
1958            let op = if matches!(last_token, Token::And) {
1959                LogicalOp::And
1960            } else {
1961                LogicalOp::Or
1962            };
1963            return (CursorContext::AfterLogicalOp(op), None);
1964        }
1965    }
1966
1967    // Check if we're in ORDER BY clause using tokens
1968    if let Some(order_pos) = find_last_token(&tokens, &Token::OrderBy) {
1969        // Check if there's a BY token after ORDER
1970        let has_by = tokens
1971            .iter()
1972            .any(|(pos, _, t)| *pos > order_pos && matches!(t, Token::By));
1973        if has_by
1974            || tokens
1975                .last()
1976                .map_or(false, |(_, _, t)| matches!(t, Token::OrderBy))
1977        {
1978            return (CursorContext::OrderByClause, extract_partial_at_end(query));
1979        }
1980    }
1981
1982    // Check if we're in WHERE clause using tokens
1983    if is_in_clause(&tokens, Token::Where, &[Token::OrderBy, Token::GroupBy]) {
1984        return (CursorContext::WhereClause, extract_partial_at_end(query));
1985    }
1986
1987    // Check if we're in FROM clause using tokens
1988    if is_in_clause(
1989        &tokens,
1990        Token::From,
1991        &[Token::Where, Token::OrderBy, Token::GroupBy],
1992    ) {
1993        return (CursorContext::FromClause, extract_partial_at_end(query));
1994    }
1995
1996    // Check if we're in SELECT clause using tokens
1997    if find_last_token(&tokens, &Token::Select).is_some()
1998        && find_last_token(&tokens, &Token::From).is_none()
1999    {
2000        return (CursorContext::SelectClause, extract_partial_at_end(query));
2001    }
2002
2003    (CursorContext::Unknown, None)
2004}
2005
2006fn extract_partial_at_end(query: &str) -> Option<String> {
2007    let trimmed = query.trim();
2008
2009    // First check if the last word itself starts with a quote (unclosed quoted identifier being typed)
2010    if let Some(last_word) = trimmed.split_whitespace().last() {
2011        if last_word.starts_with('"') && !last_word.ends_with('"') {
2012            // This is an unclosed quoted identifier like "Cust
2013            return Some(last_word.to_string());
2014        }
2015    }
2016
2017    // Regular identifier extraction
2018    let last_word = trimmed.split_whitespace().last()?;
2019
2020    // Check if it's a partial identifier (not a keyword or operator)
2021    // First check if it's alphanumeric (potential identifier)
2022    if last_word.chars().all(|c| c.is_alphanumeric() || c == '_') {
2023        // Use lexer to determine if it's a keyword or identifier
2024        if !is_sql_keyword(last_word) {
2025            Some(last_word.to_string())
2026        } else {
2027            None
2028        }
2029    } else {
2030        None
2031    }
2032}
2033
2034// Implement the ParsePrimary trait for Parser to use the modular expression parsing
2035impl ParsePrimary for Parser {
2036    fn current_token(&self) -> &Token {
2037        &self.current_token
2038    }
2039
2040    fn advance(&mut self) {
2041        self.advance();
2042    }
2043
2044    fn consume(&mut self, expected: Token) -> Result<(), String> {
2045        self.consume(expected)
2046    }
2047
2048    fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
2049        self.parse_case_expression()
2050    }
2051
2052    fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
2053        self.parse_function_args()
2054    }
2055
2056    fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
2057        self.parse_window_spec()
2058    }
2059
2060    fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
2061        self.parse_logical_or()
2062    }
2063
2064    fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2065        self.parse_comparison()
2066    }
2067
2068    fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2069        self.parse_expression_list()
2070    }
2071
2072    fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2073        // Parse subquery without parenthesis balance validation
2074        if matches!(self.current_token, Token::With) {
2075            self.parse_with_clause_inner()
2076        } else {
2077            self.parse_select_statement_inner()
2078        }
2079    }
2080}
2081
2082// Implement the ExpressionParser trait for Parser to use the modular expression parsing
2083impl ExpressionParser for Parser {
2084    fn current_token(&self) -> &Token {
2085        &self.current_token
2086    }
2087
2088    fn advance(&mut self) {
2089        // Call the main advance method directly to avoid recursion
2090        match &self.current_token {
2091            Token::LeftParen => self.paren_depth += 1,
2092            Token::RightParen => {
2093                self.paren_depth -= 1;
2094            }
2095            _ => {}
2096        }
2097        self.current_token = self.lexer.next_token();
2098    }
2099
2100    fn peek(&self) -> Option<&Token> {
2101        // We can't return a reference to a token from a temporary lexer,
2102        // so we need a different approach. For now, let's use a workaround
2103        // that checks the next token type without consuming it.
2104        // This is a limitation of the current design.
2105        // A proper fix would be to store the peeked token in the Parser struct.
2106        None // TODO: Implement proper lookahead
2107    }
2108
2109    fn is_at_end(&self) -> bool {
2110        matches!(self.current_token, Token::Eof)
2111    }
2112
2113    fn consume(&mut self, expected: Token) -> Result<(), String> {
2114        // Call the main consume method to avoid recursion
2115        if std::mem::discriminant(&self.current_token) == std::mem::discriminant(&expected) {
2116            self.update_paren_depth(&expected)?;
2117            self.current_token = self.lexer.next_token();
2118            Ok(())
2119        } else {
2120            Err(format!(
2121                "Expected {:?}, found {:?}",
2122                expected, self.current_token
2123            ))
2124        }
2125    }
2126
2127    fn parse_identifier(&mut self) -> Result<String, String> {
2128        if let Token::Identifier(id) = &self.current_token {
2129            let id = id.clone();
2130            self.advance();
2131            Ok(id)
2132        } else {
2133            Err(format!(
2134                "Expected identifier, found {:?}",
2135                self.current_token
2136            ))
2137        }
2138    }
2139}
2140
2141// Implement the ParseArithmetic trait for Parser to use the modular arithmetic parsing
2142impl ParseArithmetic for Parser {
2143    fn current_token(&self) -> &Token {
2144        &self.current_token
2145    }
2146
2147    fn advance(&mut self) {
2148        self.advance();
2149    }
2150
2151    fn consume(&mut self, expected: Token) -> Result<(), String> {
2152        self.consume(expected)
2153    }
2154
2155    fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2156        self.parse_primary()
2157    }
2158
2159    fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
2160        self.parse_multiplicative()
2161    }
2162
2163    fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
2164        self.parse_method_args()
2165    }
2166}
2167
2168// Implement the ParseComparison trait for Parser to use the modular comparison parsing
2169impl ParseComparison for Parser {
2170    fn current_token(&self) -> &Token {
2171        &self.current_token
2172    }
2173
2174    fn advance(&mut self) {
2175        self.advance();
2176    }
2177
2178    fn consume(&mut self, expected: Token) -> Result<(), String> {
2179        self.consume(expected)
2180    }
2181
2182    fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2183        self.parse_primary()
2184    }
2185
2186    fn parse_additive(&mut self) -> Result<SqlExpression, String> {
2187        self.parse_additive()
2188    }
2189
2190    fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2191        self.parse_expression_list()
2192    }
2193
2194    fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2195        // Parse subquery without parenthesis balance validation
2196        if matches!(self.current_token, Token::With) {
2197            self.parse_with_clause_inner()
2198        } else {
2199            self.parse_select_statement_inner()
2200        }
2201    }
2202}
2203
2204// Implement the ParseLogical trait for Parser to use the modular logical parsing
2205impl ParseLogical for Parser {
2206    fn current_token(&self) -> &Token {
2207        &self.current_token
2208    }
2209
2210    fn advance(&mut self) {
2211        self.advance();
2212    }
2213
2214    fn consume(&mut self, expected: Token) -> Result<(), String> {
2215        self.consume(expected)
2216    }
2217
2218    fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
2219        self.parse_logical_and()
2220    }
2221
2222    fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String> {
2223        // This is the base for logical AND - it should parse comparison expressions
2224        // to avoid infinite recursion with parse_expression
2225        self.parse_comparison()
2226    }
2227
2228    fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2229        self.parse_comparison()
2230    }
2231
2232    fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2233        self.parse_expression_list()
2234    }
2235}
2236
2237// Implement the ParseCase trait for Parser to use the modular CASE parsing
2238impl ParseCase for Parser {
2239    fn current_token(&self) -> &Token {
2240        &self.current_token
2241    }
2242
2243    fn advance(&mut self) {
2244        self.advance();
2245    }
2246
2247    fn consume(&mut self, expected: Token) -> Result<(), String> {
2248        self.consume(expected)
2249    }
2250
2251    fn parse_expression(&mut self) -> Result<SqlExpression, String> {
2252        self.parse_expression()
2253    }
2254}
2255
2256fn is_sql_keyword(word: &str) -> bool {
2257    // Use the lexer to check if this word produces a keyword token
2258    let mut lexer = Lexer::new(word);
2259    let token = lexer.next_token();
2260
2261    // Check if it's a keyword token (not an identifier)
2262    !matches!(token, Token::Identifier(_) | Token::Eof)
2263}