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