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