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