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};
35pub struct Parser {
36 lexer: Lexer,
37 current_token: Token,
38 in_method_args: bool, columns: Vec<String>, paren_depth: i32, #[allow(dead_code)]
42 config: ParserConfig, }
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 match &expected {
84 Token::LeftParen => self.paren_depth += 1,
85 Token::RightParen => {
86 self.paren_depth -= 1;
87 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 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 match &self.current_token {
127 Token::LeftParen => self.paren_depth += 1,
128 Token::RightParen => {
129 self.paren_depth -= 1;
130 }
133 _ => {}
134 }
135 self.current_token = self.lexer.next_token();
136 }
137
138 pub fn parse(&mut self) -> Result<SelectStatement, String> {
139 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 loop {
154 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 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 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 self.consume(Token::As)?;
190
191 self.consume(Token::LeftParen)?;
193
194 let cte_type = if is_web {
195 let web_spec = self.parse_web_cte_spec()?;
197 CTEType::Web(web_spec)
198 } else {
199 let query = self.parse_select_statement_inner()?;
201 CTEType::Standard(query)
202 };
203
204 self.consume(Token::RightParen)?;
206
207 ctes.push(CTE {
208 name,
209 column_list,
210 cte_type,
211 });
212
213 if !matches!(self.current_token, Token::Comma) {
215 break;
216 }
217 self.advance();
218 }
219
220 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 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 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 let mut format = None;
247 let mut headers = Vec::new();
248 let mut cache_seconds = None;
249
250 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 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 if !matches!(self.current_token, Token::Colon) {
332 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(); }
341
342 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 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 loop {
369 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 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 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 self.consume(Token::As)?;
400
401 self.consume(Token::LeftParen)?;
403
404 let cte_type = if is_web {
405 let web_spec = self.parse_web_cte_spec()?;
407 CTEType::Web(web_spec)
408 } else {
409 let query = self.parse_select_statement_inner()?;
411 CTEType::Standard(query)
412 };
413
414 self.consume(Token::RightParen)?;
416
417 ctes.push(CTE {
418 name,
419 column_list,
420 cte_type,
421 });
422
423 if !matches!(self.current_token, Token::Comma) {
425 break;
426 }
427 self.advance();
428 }
429
430 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 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 let distinct = if matches!(self.current_token, Token::Distinct) {
461 self.advance();
462 true
463 } else {
464 false
465 };
466
467 let select_items = self.parse_select_items()?;
469
470 let columns = select_items
472 .iter()
473 .map(|item| match item {
474 SelectItem::Star => "*".to_string(),
475 SelectItem::Column(name) => name.clone(),
476 SelectItem::Expression { alias, .. } => alias.clone(),
477 })
478 .collect();
479
480 let (from_table, from_subquery, from_function, from_alias) =
482 if matches!(self.current_token, Token::From) {
483 self.advance();
484
485 if let Token::Identifier(name) = &self.current_token.clone() {
487 if name.to_uppercase() == "RANGE" {
488 self.advance();
489 self.consume(Token::LeftParen)?;
491
492 let start = self.parse_expression()?;
494 self.consume(Token::Comma)?;
495
496 let end = self.parse_expression()?;
498
499 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 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 {
535 let table_name = name.clone();
537 self.advance();
538
539 let alias = if matches!(self.current_token, Token::As) {
541 self.advance();
542 match &self.current_token {
543 Token::Identifier(name) => {
544 let alias = name.clone();
545 self.advance();
546 Some(alias)
547 }
548 _ => return Err("Expected alias name after AS".to_string()),
549 }
550 } else if let Token::Identifier(name) = &self.current_token {
551 let alias = name.clone();
553 self.advance();
554 Some(alias)
555 } else {
556 None
557 };
558
559 (Some(table_name), None, None, alias)
560 }
561 } else if matches!(self.current_token, Token::LeftParen) {
562 self.advance();
564
565 let subquery = self.parse_select_statement_inner()?;
567
568 self.consume(Token::RightParen)?;
569
570 let alias = if matches!(self.current_token, Token::As) {
572 self.advance();
573 match &self.current_token {
574 Token::Identifier(name) => {
575 let alias = name.clone();
576 self.advance();
577 alias
578 }
579 _ => return Err("Expected alias name after AS".to_string()),
580 }
581 } else {
582 match &self.current_token {
584 Token::Identifier(name) => {
585 let alias = name.clone();
586 self.advance();
587 alias
588 }
589 _ => {
590 return Err(
591 "Subquery in FROM must have an alias (e.g., AS t)".to_string()
592 )
593 }
594 }
595 };
596
597 (None, Some(Box::new(subquery)), None, Some(alias))
598 } else {
599 match &self.current_token {
601 Token::Identifier(table) => {
602 let table_name = table.clone();
603 self.advance();
604
605 let alias = if matches!(self.current_token, Token::As) {
607 self.advance();
608 match &self.current_token {
609 Token::Identifier(name) => {
610 let alias = name.clone();
611 self.advance();
612 Some(alias)
613 }
614 _ => return Err("Expected alias name after AS".to_string()),
615 }
616 } else if let Token::Identifier(name) = &self.current_token {
617 let alias = name.clone();
619 self.advance();
620 Some(alias)
621 } else {
622 None
623 };
624
625 (Some(table_name), None, None, alias)
626 }
627 Token::QuotedIdentifier(table) => {
628 let table_name = table.clone();
630 self.advance();
631
632 let alias = if matches!(self.current_token, Token::As) {
634 self.advance();
635 match &self.current_token {
636 Token::Identifier(name) => {
637 let alias = name.clone();
638 self.advance();
639 Some(alias)
640 }
641 _ => return Err("Expected alias name after AS".to_string()),
642 }
643 } else if let Token::Identifier(name) = &self.current_token {
644 let alias = name.clone();
646 self.advance();
647 Some(alias)
648 } else {
649 None
650 };
651
652 (Some(table_name), None, None, alias)
653 }
654 _ => return Err("Expected table name or subquery after FROM".to_string()),
655 }
656 }
657 } else {
658 (None, None, None, None)
659 };
660
661 let mut joins = Vec::new();
663 while self.is_join_token() {
664 joins.push(self.parse_join_clause()?);
665 }
666
667 let where_clause = if matches!(self.current_token, Token::Where) {
668 self.advance();
669 Some(self.parse_where_clause()?)
670 } else {
671 None
672 };
673
674 let group_by = if matches!(self.current_token, Token::GroupBy) {
675 self.advance();
676 Some(self.parse_expression_list()?)
679 } else {
680 None
681 };
682
683 let having = if matches!(self.current_token, Token::Having) {
685 if group_by.is_none() {
686 return Err("HAVING clause requires GROUP BY".to_string());
687 }
688 self.advance();
689 Some(self.parse_expression()?)
690 } else {
691 None
692 };
693
694 let order_by = if matches!(self.current_token, Token::OrderBy) {
696 self.advance();
697 Some(self.parse_order_by_list()?)
698 } else if let Token::Identifier(s) = &self.current_token {
699 if s.to_uppercase() == "ORDER" {
700 self.advance(); if matches!(&self.current_token, Token::Identifier(by_token) if by_token.to_uppercase() == "BY")
703 {
704 self.advance(); Some(self.parse_order_by_list()?)
706 } else {
707 return Err("Expected BY after ORDER".to_string());
708 }
709 } else {
710 None
711 }
712 } else {
713 None
714 };
715
716 let limit = if matches!(self.current_token, Token::Limit) {
718 self.advance();
719 match &self.current_token {
720 Token::NumberLiteral(num) => {
721 let limit_val = num
722 .parse::<usize>()
723 .map_err(|_| format!("Invalid LIMIT value: {num}"))?;
724 self.advance();
725 Some(limit_val)
726 }
727 _ => return Err("Expected number after LIMIT".to_string()),
728 }
729 } else {
730 None
731 };
732
733 let offset = if matches!(self.current_token, Token::Offset) {
735 self.advance();
736 match &self.current_token {
737 Token::NumberLiteral(num) => {
738 let offset_val = num
739 .parse::<usize>()
740 .map_err(|_| format!("Invalid OFFSET value: {num}"))?;
741 self.advance();
742 Some(offset_val)
743 }
744 _ => return Err("Expected number after OFFSET".to_string()),
745 }
746 } else {
747 None
748 };
749
750 Ok(SelectStatement {
751 distinct,
752 columns,
753 select_items,
754 from_table,
755 from_subquery,
756 from_function,
757 from_alias,
758 joins,
759 where_clause,
760 order_by,
761 group_by,
762 having,
763 limit,
764 offset,
765 ctes: Vec::new(), })
767 }
768
769 fn parse_select_list(&mut self) -> Result<Vec<String>, String> {
770 let mut columns = Vec::new();
771
772 if matches!(self.current_token, Token::Star) {
773 columns.push("*".to_string());
774 self.advance();
775 } else {
776 loop {
777 match &self.current_token {
778 Token::Identifier(col) => {
779 columns.push(col.clone());
780 self.advance();
781 }
782 Token::QuotedIdentifier(col) => {
783 columns.push(col.clone());
785 self.advance();
786 }
787 _ => return Err("Expected column name".to_string()),
788 }
789
790 if matches!(self.current_token, Token::Comma) {
791 self.advance();
792 } else {
793 break;
794 }
795 }
796 }
797
798 Ok(columns)
799 }
800
801 fn parse_select_items(&mut self) -> Result<Vec<SelectItem>, String> {
803 let mut items = Vec::new();
804
805 loop {
806 if matches!(self.current_token, Token::Star) {
809 items.push(SelectItem::Star);
817 self.advance();
818 } else {
819 let expr = self.parse_comparison()?; let alias = if matches!(self.current_token, Token::As) {
824 self.advance();
825 match &self.current_token {
826 Token::Identifier(alias_name) => {
827 let alias = alias_name.clone();
828 self.advance();
829 alias
830 }
831 Token::QuotedIdentifier(alias_name) => {
832 let alias = alias_name.clone();
833 self.advance();
834 alias
835 }
836 _ => return Err("Expected alias name after AS".to_string()),
837 }
838 } else {
839 match &expr {
841 SqlExpression::Column(col_name) => col_name.clone(),
842 _ => format!("expr_{}", items.len() + 1), }
844 };
845
846 let item = match expr {
848 SqlExpression::Column(col_name) if alias == col_name => {
849 SelectItem::Column(col_name)
851 }
852 _ => {
853 SelectItem::Expression { expr, alias }
855 }
856 };
857
858 items.push(item);
859 }
860
861 if matches!(self.current_token, Token::Comma) {
863 self.advance();
864 } else {
865 break;
866 }
867 }
868
869 Ok(items)
870 }
871
872 fn parse_identifier_list(&mut self) -> Result<Vec<String>, String> {
873 let mut identifiers = Vec::new();
874
875 loop {
876 match &self.current_token {
877 Token::Identifier(id) => {
878 let id_upper = id.to_uppercase();
880 if matches!(
881 id_upper.as_str(),
882 "ORDER" | "HAVING" | "LIMIT" | "OFFSET" | "UNION" | "INTERSECT" | "EXCEPT"
883 ) {
884 break;
886 }
887 identifiers.push(id.clone());
888 self.advance();
889 }
890 Token::QuotedIdentifier(id) => {
891 identifiers.push(id.clone());
893 self.advance();
894 }
895 _ => {
896 break;
898 }
899 }
900
901 if matches!(self.current_token, Token::Comma) {
902 self.advance();
903 } else {
904 break;
905 }
906 }
907
908 if identifiers.is_empty() {
909 return Err("Expected at least one identifier".to_string());
910 }
911
912 Ok(identifiers)
913 }
914
915 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
916 let mut partition_by = Vec::new();
917 let mut order_by = Vec::new();
918
919 if matches!(self.current_token, Token::Partition) {
921 self.advance(); if !matches!(self.current_token, Token::By) {
923 return Err("Expected BY after PARTITION".to_string());
924 }
925 self.advance(); partition_by = self.parse_identifier_list()?;
929 }
930
931 if matches!(self.current_token, Token::OrderBy) {
933 self.advance(); order_by = self.parse_order_by_list()?;
935 } else if let Token::Identifier(s) = &self.current_token {
936 if s.to_uppercase() == "ORDER" {
937 self.advance(); if !matches!(self.current_token, Token::By) {
940 return Err("Expected BY after ORDER".to_string());
941 }
942 self.advance(); order_by = self.parse_order_by_list()?;
944 }
945 }
946
947 let frame = self.parse_window_frame()?;
949
950 Ok(WindowSpec {
951 partition_by,
952 order_by,
953 frame,
954 })
955 }
956
957 fn parse_order_by_list(&mut self) -> Result<Vec<OrderByColumn>, String> {
958 let mut order_columns = Vec::new();
959
960 loop {
961 let column = match &self.current_token {
962 Token::Identifier(id) => {
963 let col = id.clone();
964 self.advance();
965 col
966 }
967 Token::QuotedIdentifier(id) => {
968 let col = id.clone();
969 self.advance();
970 col
971 }
972 Token::NumberLiteral(num) if self.columns.iter().any(|col| col == num) => {
973 let col = num.clone();
975 self.advance();
976 col
977 }
978 _ => return Err("Expected column name in ORDER BY".to_string()),
979 };
980
981 let direction = match &self.current_token {
983 Token::Asc => {
984 self.advance();
985 SortDirection::Asc
986 }
987 Token::Desc => {
988 self.advance();
989 SortDirection::Desc
990 }
991 _ => SortDirection::Asc, };
993
994 order_columns.push(OrderByColumn { column, direction });
995
996 if matches!(self.current_token, Token::Comma) {
997 self.advance();
998 } else {
999 break;
1000 }
1001 }
1002
1003 Ok(order_columns)
1004 }
1005
1006 fn parse_window_frame(&mut self) -> Result<Option<WindowFrame>, String> {
1007 let unit = match &self.current_token {
1009 Token::Identifier(id) if id.to_uppercase() == "ROWS" => {
1010 self.advance();
1011 FrameUnit::Rows
1012 }
1013 Token::Identifier(id) if id.to_uppercase() == "RANGE" => {
1014 self.advance();
1015 FrameUnit::Range
1016 }
1017 _ => return Ok(None), };
1019
1020 let (start, end) = if let Token::Between = &self.current_token {
1022 self.advance(); let start = self.parse_frame_bound()?;
1025
1026 if !matches!(&self.current_token, Token::And) {
1028 return Err("Expected AND after window frame start bound".to_string());
1029 }
1030 self.advance();
1031
1032 let end = self.parse_frame_bound()?;
1034 (start, Some(end))
1035 } else {
1036 let bound = self.parse_frame_bound()?;
1038 (bound, None)
1039 };
1040
1041 Ok(Some(WindowFrame { unit, start, end }))
1042 }
1043
1044 fn parse_frame_bound(&mut self) -> Result<FrameBound, String> {
1045 match &self.current_token {
1046 Token::Identifier(id) if id.to_uppercase() == "UNBOUNDED" => {
1047 self.advance();
1048 match &self.current_token {
1049 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1050 self.advance();
1051 Ok(FrameBound::UnboundedPreceding)
1052 }
1053 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1054 self.advance();
1055 Ok(FrameBound::UnboundedFollowing)
1056 }
1057 _ => Err("Expected PRECEDING or FOLLOWING after UNBOUNDED".to_string()),
1058 }
1059 }
1060 Token::Identifier(id) if id.to_uppercase() == "CURRENT" => {
1061 self.advance();
1062 if let Token::Identifier(id) = &self.current_token {
1063 if id.to_uppercase() == "ROW" {
1064 self.advance();
1065 return Ok(FrameBound::CurrentRow);
1066 }
1067 }
1068 Err("Expected ROW after CURRENT".to_string())
1069 }
1070 Token::NumberLiteral(num) => {
1071 let n: i64 = num
1072 .parse()
1073 .map_err(|_| "Invalid number in window frame".to_string())?;
1074 self.advance();
1075 match &self.current_token {
1076 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1077 self.advance();
1078 Ok(FrameBound::Preceding(n))
1079 }
1080 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1081 self.advance();
1082 Ok(FrameBound::Following(n))
1083 }
1084 _ => Err("Expected PRECEDING or FOLLOWING after number".to_string()),
1085 }
1086 }
1087 _ => Err("Invalid window frame bound".to_string()),
1088 }
1089 }
1090
1091 fn parse_where_clause(&mut self) -> Result<WhereClause, String> {
1092 let expr = self.parse_expression()?;
1095
1096 if matches!(self.current_token, Token::RightParen) && self.paren_depth <= 0 {
1098 return Err(
1099 "Unexpected closing parenthesis - no matching opening parenthesis".to_string(),
1100 );
1101 }
1102
1103 let conditions = vec![Condition {
1105 expr,
1106 connector: None,
1107 }];
1108
1109 Ok(WhereClause { conditions })
1110 }
1111
1112 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
1113 let mut left = self.parse_logical_or()?;
1116
1117 left = parse_in_operator(self, left)?;
1120
1121 Ok(left)
1122 }
1123
1124 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1125 parse_comparison_expr(self)
1127 }
1128
1129 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
1130 parse_additive_expr(self)
1132 }
1133
1134 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
1135 parse_multiplicative_expr(self)
1137 }
1138
1139 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1140 parse_logical_or_expr(self)
1142 }
1143
1144 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
1145 parse_logical_and_expr(self)
1147 }
1148
1149 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1150 parse_case_expr(self)
1152 }
1153
1154 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
1155 let columns = self.columns.clone();
1158 let in_method_args = self.in_method_args;
1159 let ctx = PrimaryExpressionContext {
1160 columns: &columns,
1161 in_method_args,
1162 };
1163 parse_primary_expr(self, &ctx)
1164 }
1165
1166 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
1168 let mut args = Vec::new();
1169
1170 self.in_method_args = true;
1172
1173 if !matches!(self.current_token, Token::RightParen) {
1174 loop {
1175 args.push(self.parse_expression()?);
1176
1177 if matches!(self.current_token, Token::Comma) {
1178 self.advance();
1179 } else {
1180 break;
1181 }
1182 }
1183 }
1184
1185 self.in_method_args = false;
1187
1188 Ok(args)
1189 }
1190
1191 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1192 let mut args = Vec::new();
1193 let mut has_distinct = false;
1194
1195 if !matches!(self.current_token, Token::RightParen) {
1196 if matches!(self.current_token, Token::Distinct) {
1198 self.advance(); has_distinct = true;
1200 }
1201
1202 args.push(self.parse_additive()?);
1204
1205 while matches!(self.current_token, Token::Comma) {
1207 self.advance();
1208 args.push(self.parse_additive()?);
1209 }
1210 }
1211
1212 Ok((args, has_distinct))
1213 }
1214
1215 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1216 let mut expressions = Vec::new();
1217
1218 loop {
1219 expressions.push(self.parse_expression()?);
1220
1221 if matches!(self.current_token, Token::Comma) {
1222 self.advance();
1223 } else {
1224 break;
1225 }
1226 }
1227
1228 Ok(expressions)
1229 }
1230
1231 fn get_binary_op(&self) -> Option<String> {
1232 match &self.current_token {
1233 Token::Equal => Some("=".to_string()),
1234 Token::NotEqual => Some("!=".to_string()),
1235 Token::LessThan => Some("<".to_string()),
1236 Token::GreaterThan => Some(">".to_string()),
1237 Token::LessThanOrEqual => Some("<=".to_string()),
1238 Token::GreaterThanOrEqual => Some(">=".to_string()),
1239 Token::Like => Some("LIKE".to_string()),
1240 _ => None,
1241 }
1242 }
1243
1244 fn get_arithmetic_op(&self) -> Option<String> {
1245 match &self.current_token {
1246 Token::Plus => Some("+".to_string()),
1247 Token::Minus => Some("-".to_string()),
1248 Token::Star => Some("*".to_string()), Token::Divide => Some("/".to_string()),
1250 Token::Modulo => Some("%".to_string()),
1251 _ => None,
1252 }
1253 }
1254
1255 #[must_use]
1256 pub fn get_position(&self) -> usize {
1257 self.lexer.get_position()
1258 }
1259
1260 fn is_join_token(&self) -> bool {
1262 matches!(
1263 self.current_token,
1264 Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
1265 )
1266 }
1267
1268 fn parse_join_clause(&mut self) -> Result<JoinClause, String> {
1270 let join_type = match &self.current_token {
1272 Token::Join => {
1273 self.advance();
1274 JoinType::Inner }
1276 Token::Inner => {
1277 self.advance();
1278 if !matches!(self.current_token, Token::Join) {
1279 return Err("Expected JOIN after INNER".to_string());
1280 }
1281 self.advance();
1282 JoinType::Inner
1283 }
1284 Token::Left => {
1285 self.advance();
1286 if matches!(self.current_token, Token::Outer) {
1288 self.advance();
1289 }
1290 if !matches!(self.current_token, Token::Join) {
1291 return Err("Expected JOIN after LEFT".to_string());
1292 }
1293 self.advance();
1294 JoinType::Left
1295 }
1296 Token::Right => {
1297 self.advance();
1298 if matches!(self.current_token, Token::Outer) {
1300 self.advance();
1301 }
1302 if !matches!(self.current_token, Token::Join) {
1303 return Err("Expected JOIN after RIGHT".to_string());
1304 }
1305 self.advance();
1306 JoinType::Right
1307 }
1308 Token::Full => {
1309 self.advance();
1310 if matches!(self.current_token, Token::Outer) {
1312 self.advance();
1313 }
1314 if !matches!(self.current_token, Token::Join) {
1315 return Err("Expected JOIN after FULL".to_string());
1316 }
1317 self.advance();
1318 JoinType::Full
1319 }
1320 Token::Cross => {
1321 self.advance();
1322 if !matches!(self.current_token, Token::Join) {
1323 return Err("Expected JOIN after CROSS".to_string());
1324 }
1325 self.advance();
1326 JoinType::Cross
1327 }
1328 _ => return Err("Expected JOIN keyword".to_string()),
1329 };
1330
1331 let (table, alias) = self.parse_join_table_source()?;
1333
1334 let condition = if join_type == JoinType::Cross {
1336 JoinCondition {
1338 left_column: String::new(),
1339 operator: JoinOperator::Equal,
1340 right_column: String::new(),
1341 }
1342 } else {
1343 if !matches!(self.current_token, Token::On) {
1344 return Err("Expected ON keyword after JOIN table".to_string());
1345 }
1346 self.advance();
1347 self.parse_join_condition()?
1348 };
1349
1350 Ok(JoinClause {
1351 join_type,
1352 table,
1353 alias,
1354 condition,
1355 })
1356 }
1357
1358 fn parse_join_table_source(&mut self) -> Result<(TableSource, Option<String>), String> {
1359 let table = match &self.current_token {
1360 Token::Identifier(name) => {
1361 let table_name = name.clone();
1362 self.advance();
1363 TableSource::Table(table_name)
1364 }
1365 Token::LeftParen => {
1366 self.advance();
1368 let subquery = self.parse_select_statement_inner()?;
1369 if !matches!(self.current_token, Token::RightParen) {
1370 return Err("Expected ')' after subquery".to_string());
1371 }
1372 self.advance();
1373
1374 let alias = match &self.current_token {
1376 Token::Identifier(alias_name) => {
1377 let alias = alias_name.clone();
1378 self.advance();
1379 alias
1380 }
1381 Token::As => {
1382 self.advance();
1383 match &self.current_token {
1384 Token::Identifier(alias_name) => {
1385 let alias = alias_name.clone();
1386 self.advance();
1387 alias
1388 }
1389 _ => return Err("Expected alias after AS keyword".to_string()),
1390 }
1391 }
1392 _ => return Err("Subqueries must have an alias".to_string()),
1393 };
1394
1395 return Ok((
1396 TableSource::DerivedTable {
1397 query: Box::new(subquery),
1398 alias: alias.clone(),
1399 },
1400 Some(alias),
1401 ));
1402 }
1403 _ => return Err("Expected table name or subquery in JOIN clause".to_string()),
1404 };
1405
1406 let alias = match &self.current_token {
1408 Token::Identifier(alias_name) => {
1409 let alias = alias_name.clone();
1410 self.advance();
1411 Some(alias)
1412 }
1413 Token::As => {
1414 self.advance();
1415 match &self.current_token {
1416 Token::Identifier(alias_name) => {
1417 let alias = alias_name.clone();
1418 self.advance();
1419 Some(alias)
1420 }
1421 _ => return Err("Expected alias after AS keyword".to_string()),
1422 }
1423 }
1424 _ => None,
1425 };
1426
1427 Ok((table, alias))
1428 }
1429
1430 fn parse_join_condition(&mut self) -> Result<JoinCondition, String> {
1431 let left_column = self.parse_column_reference()?;
1433
1434 let operator = match &self.current_token {
1436 Token::Equal => JoinOperator::Equal,
1437 Token::NotEqual => JoinOperator::NotEqual,
1438 Token::LessThan => JoinOperator::LessThan,
1439 Token::LessThanOrEqual => JoinOperator::LessThanOrEqual,
1440 Token::GreaterThan => JoinOperator::GreaterThan,
1441 Token::GreaterThanOrEqual => JoinOperator::GreaterThanOrEqual,
1442 _ => return Err("Expected comparison operator in JOIN condition".to_string()),
1443 };
1444 self.advance();
1445
1446 let right_column = self.parse_column_reference()?;
1448
1449 Ok(JoinCondition {
1450 left_column,
1451 operator,
1452 right_column,
1453 })
1454 }
1455
1456 fn parse_column_reference(&mut self) -> Result<String, String> {
1457 match &self.current_token {
1458 Token::Identifier(name) => {
1459 let mut column_ref = name.clone();
1460 self.advance();
1461
1462 if matches!(self.current_token, Token::Dot) {
1464 self.advance();
1465 match &self.current_token {
1466 Token::Identifier(col_name) => {
1467 column_ref.push('.');
1468 column_ref.push_str(col_name);
1469 self.advance();
1470 }
1471 _ => return Err("Expected column name after '.'".to_string()),
1472 }
1473 }
1474
1475 Ok(column_ref)
1476 }
1477 _ => Err("Expected column reference".to_string()),
1478 }
1479 }
1480}
1481
1482#[derive(Debug, Clone)]
1484pub enum CursorContext {
1485 SelectClause,
1486 FromClause,
1487 WhereClause,
1488 OrderByClause,
1489 AfterColumn(String),
1490 AfterLogicalOp(LogicalOp),
1491 AfterComparisonOp(String, String), InMethodCall(String, String), InExpression,
1494 Unknown,
1495}
1496
1497fn safe_slice_to(s: &str, pos: usize) -> &str {
1499 if pos >= s.len() {
1500 return s;
1501 }
1502
1503 let mut safe_pos = pos;
1505 while safe_pos > 0 && !s.is_char_boundary(safe_pos) {
1506 safe_pos -= 1;
1507 }
1508
1509 &s[..safe_pos]
1510}
1511
1512fn safe_slice_from(s: &str, pos: usize) -> &str {
1514 if pos >= s.len() {
1515 return "";
1516 }
1517
1518 let mut safe_pos = pos;
1520 while safe_pos < s.len() && !s.is_char_boundary(safe_pos) {
1521 safe_pos += 1;
1522 }
1523
1524 &s[safe_pos..]
1525}
1526
1527#[must_use]
1528pub fn detect_cursor_context(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1529 let truncated = safe_slice_to(query, cursor_pos);
1530 let mut parser = Parser::new(truncated);
1531
1532 if let Ok(stmt) = parser.parse() {
1534 let (ctx, partial) = analyze_statement(&stmt, truncated, cursor_pos);
1535 #[cfg(test)]
1536 println!("analyze_statement returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1537 (ctx, partial)
1538 } else {
1539 let (ctx, partial) = analyze_partial(truncated, cursor_pos);
1541 #[cfg(test)]
1542 println!("analyze_partial returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1543 (ctx, partial)
1544 }
1545}
1546
1547#[must_use]
1548pub fn tokenize_query(query: &str) -> Vec<String> {
1549 let mut lexer = Lexer::new(query);
1550 let tokens = lexer.tokenize_all();
1551 tokens.iter().map(|t| format!("{t:?}")).collect()
1552}
1553
1554#[must_use]
1555fn analyze_statement(
1556 stmt: &SelectStatement,
1557 query: &str,
1558 _cursor_pos: usize,
1559) -> (CursorContext, Option<String>) {
1560 let trimmed = query.trim();
1562
1563 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1565 for op in &comparison_ops {
1566 if let Some(op_pos) = query.rfind(op) {
1567 let before_op = safe_slice_to(query, op_pos);
1568 let after_op_start = op_pos + op.len();
1569 let after_op = if after_op_start < query.len() {
1570 &query[after_op_start..]
1571 } else {
1572 ""
1573 };
1574
1575 if let Some(col_name) = before_op.split_whitespace().last() {
1577 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1578 let after_op_trimmed = after_op.trim();
1580 if after_op_trimmed.is_empty()
1581 || (after_op_trimmed
1582 .chars()
1583 .all(|c| c.is_alphanumeric() || c == '_')
1584 && !after_op_trimmed.contains('('))
1585 {
1586 let partial = if after_op_trimmed.is_empty() {
1587 None
1588 } else {
1589 Some(after_op_trimmed.to_string())
1590 };
1591 return (
1592 CursorContext::AfterComparisonOp(
1593 col_name.to_string(),
1594 op.trim().to_string(),
1595 ),
1596 partial,
1597 );
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 if trimmed.to_uppercase().ends_with(" AND")
1606 || trimmed.to_uppercase().ends_with(" OR")
1607 || trimmed.to_uppercase().ends_with(" AND ")
1608 || trimmed.to_uppercase().ends_with(" OR ")
1609 {
1610 } else {
1612 if let Some(dot_pos) = trimmed.rfind('.') {
1614 let before_dot = safe_slice_to(trimmed, dot_pos);
1616 let after_dot_start = dot_pos + 1;
1617 let after_dot = if after_dot_start < trimmed.len() {
1618 &trimmed[after_dot_start..]
1619 } else {
1620 ""
1621 };
1622
1623 if !after_dot.contains('(') {
1626 let col_name = if before_dot.ends_with('"') {
1628 let bytes = before_dot.as_bytes();
1630 let mut pos = before_dot.len() - 1; let mut found_start = None;
1632
1633 if pos > 0 {
1635 pos -= 1;
1636 while pos > 0 {
1637 if bytes[pos] == b'"' {
1638 if pos == 0 || bytes[pos - 1] != b'\\' {
1640 found_start = Some(pos);
1641 break;
1642 }
1643 }
1644 pos -= 1;
1645 }
1646 if found_start.is_none() && bytes[0] == b'"' {
1648 found_start = Some(0);
1649 }
1650 }
1651
1652 found_start.map(|start| safe_slice_from(before_dot, start))
1653 } else {
1654 before_dot
1657 .split_whitespace()
1658 .last()
1659 .map(|word| word.trim_start_matches('('))
1660 };
1661
1662 if let Some(col_name) = col_name {
1663 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1665 true
1667 } else {
1668 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1670 };
1671
1672 if is_valid {
1673 let partial_method = if after_dot.is_empty() {
1676 None
1677 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1678 Some(after_dot.to_string())
1679 } else {
1680 None
1681 };
1682
1683 let col_name_for_context = if col_name.starts_with('"')
1685 && col_name.ends_with('"')
1686 && col_name.len() > 2
1687 {
1688 col_name[1..col_name.len() - 1].to_string()
1689 } else {
1690 col_name.to_string()
1691 };
1692
1693 return (
1694 CursorContext::AfterColumn(col_name_for_context),
1695 partial_method,
1696 );
1697 }
1698 }
1699 }
1700 }
1701 }
1702
1703 if let Some(where_clause) = &stmt.where_clause {
1705 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1707 let op = if trimmed.to_uppercase().ends_with(" AND") {
1708 LogicalOp::And
1709 } else {
1710 LogicalOp::Or
1711 };
1712 return (CursorContext::AfterLogicalOp(op), None);
1713 }
1714
1715 if let Some(and_pos) = query.to_uppercase().rfind(" AND ") {
1717 let after_and = safe_slice_from(query, and_pos + 5);
1718 let partial = extract_partial_at_end(after_and);
1719 if partial.is_some() {
1720 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1721 }
1722 }
1723
1724 if let Some(or_pos) = query.to_uppercase().rfind(" OR ") {
1725 let after_or = safe_slice_from(query, or_pos + 4);
1726 let partial = extract_partial_at_end(after_or);
1727 if partial.is_some() {
1728 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1729 }
1730 }
1731
1732 if let Some(last_condition) = where_clause.conditions.last() {
1733 if let Some(connector) = &last_condition.connector {
1734 return (
1736 CursorContext::AfterLogicalOp(connector.clone()),
1737 extract_partial_at_end(query),
1738 );
1739 }
1740 }
1741 return (CursorContext::WhereClause, extract_partial_at_end(query));
1743 }
1744
1745 if query.to_uppercase().ends_with(" ORDER BY ") || query.to_uppercase().ends_with(" ORDER BY") {
1747 return (CursorContext::OrderByClause, None);
1748 }
1749
1750 if stmt.order_by.is_some() {
1752 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1753 }
1754
1755 if stmt.from_table.is_some() && stmt.where_clause.is_none() && stmt.order_by.is_none() {
1756 return (CursorContext::FromClause, extract_partial_at_end(query));
1757 }
1758
1759 if !stmt.columns.is_empty() && stmt.from_table.is_none() {
1760 return (CursorContext::SelectClause, extract_partial_at_end(query));
1761 }
1762
1763 (CursorContext::Unknown, None)
1764}
1765
1766fn analyze_partial(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1767 let upper = query.to_uppercase();
1768
1769 let trimmed = query.trim();
1771
1772 #[cfg(test)]
1773 {
1774 if trimmed.contains("\"Last Name\"") {
1775 eprintln!("DEBUG analyze_partial: query='{query}', trimmed='{trimmed}'");
1776 }
1777 }
1778
1779 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1781 for op in &comparison_ops {
1782 if let Some(op_pos) = query.rfind(op) {
1783 let before_op = safe_slice_to(query, op_pos);
1784 let after_op_start = op_pos + op.len();
1785 let after_op = if after_op_start < query.len() {
1786 &query[after_op_start..]
1787 } else {
1788 ""
1789 };
1790
1791 if let Some(col_name) = before_op.split_whitespace().last() {
1793 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1794 let after_op_trimmed = after_op.trim();
1796 if after_op_trimmed.is_empty()
1797 || (after_op_trimmed
1798 .chars()
1799 .all(|c| c.is_alphanumeric() || c == '_')
1800 && !after_op_trimmed.contains('('))
1801 {
1802 let partial = if after_op_trimmed.is_empty() {
1803 None
1804 } else {
1805 Some(after_op_trimmed.to_string())
1806 };
1807 return (
1808 CursorContext::AfterComparisonOp(
1809 col_name.to_string(),
1810 op.trim().to_string(),
1811 ),
1812 partial,
1813 );
1814 }
1815 }
1816 }
1817 }
1818 }
1819
1820 if let Some(dot_pos) = trimmed.rfind('.') {
1823 #[cfg(test)]
1824 {
1825 if trimmed.contains("\"Last Name\"") {
1826 eprintln!("DEBUG: Found dot at position {dot_pos}");
1827 }
1828 }
1829 let before_dot = &trimmed[..dot_pos];
1831 let after_dot = &trimmed[dot_pos + 1..];
1832
1833 if !after_dot.contains('(') {
1836 let col_name = if before_dot.ends_with('"') {
1839 let bytes = before_dot.as_bytes();
1841 let mut pos = before_dot.len() - 1; let mut found_start = None;
1843
1844 #[cfg(test)]
1845 {
1846 if trimmed.contains("\"Last Name\"") {
1847 eprintln!("DEBUG: before_dot='{before_dot}', looking for opening quote");
1848 }
1849 }
1850
1851 if pos > 0 {
1853 pos -= 1;
1854 while pos > 0 {
1855 if bytes[pos] == b'"' {
1856 if pos == 0 || bytes[pos - 1] != b'\\' {
1858 found_start = Some(pos);
1859 break;
1860 }
1861 }
1862 pos -= 1;
1863 }
1864 if found_start.is_none() && bytes[0] == b'"' {
1866 found_start = Some(0);
1867 }
1868 }
1869
1870 if let Some(start) = found_start {
1871 let result = safe_slice_from(before_dot, start);
1873 #[cfg(test)]
1874 {
1875 if trimmed.contains("\"Last Name\"") {
1876 eprintln!("DEBUG: Extracted quoted identifier: '{result}'");
1877 }
1878 }
1879 Some(result)
1880 } else {
1881 #[cfg(test)]
1882 {
1883 if trimmed.contains("\"Last Name\"") {
1884 eprintln!("DEBUG: No opening quote found!");
1885 }
1886 }
1887 None
1888 }
1889 } else {
1890 before_dot
1893 .split_whitespace()
1894 .last()
1895 .map(|word| word.trim_start_matches('('))
1896 };
1897
1898 if let Some(col_name) = col_name {
1899 #[cfg(test)]
1900 {
1901 if trimmed.contains("\"Last Name\"") {
1902 eprintln!("DEBUG: col_name = '{col_name}'");
1903 }
1904 }
1905
1906 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1908 true
1910 } else {
1911 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1913 };
1914
1915 #[cfg(test)]
1916 {
1917 if trimmed.contains("\"Last Name\"") {
1918 eprintln!("DEBUG: is_valid = {is_valid}");
1919 }
1920 }
1921
1922 if is_valid {
1923 let partial_method = if after_dot.is_empty() {
1926 None
1927 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1928 Some(after_dot.to_string())
1929 } else {
1930 None
1931 };
1932
1933 let col_name_for_context = if col_name.starts_with('"')
1935 && col_name.ends_with('"')
1936 && col_name.len() > 2
1937 {
1938 col_name[1..col_name.len() - 1].to_string()
1939 } else {
1940 col_name.to_string()
1941 };
1942
1943 return (
1944 CursorContext::AfterColumn(col_name_for_context),
1945 partial_method,
1946 );
1947 }
1948 }
1949 }
1950 }
1951
1952 if let Some(and_pos) = upper.rfind(" AND ") {
1954 if cursor_pos >= and_pos + 5 {
1956 let after_and = safe_slice_from(query, and_pos + 5);
1958 let partial = extract_partial_at_end(after_and);
1959 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1960 }
1961 }
1962
1963 if let Some(or_pos) = upper.rfind(" OR ") {
1964 if cursor_pos >= or_pos + 4 {
1966 let after_or = safe_slice_from(query, or_pos + 4);
1968 let partial = extract_partial_at_end(after_or);
1969 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1970 }
1971 }
1972
1973 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1975 let op = if trimmed.to_uppercase().ends_with(" AND") {
1976 LogicalOp::And
1977 } else {
1978 LogicalOp::Or
1979 };
1980 return (CursorContext::AfterLogicalOp(op), None);
1981 }
1982
1983 if upper.ends_with(" ORDER BY ") || upper.ends_with(" ORDER BY") || upper.contains("ORDER BY ")
1985 {
1986 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1987 }
1988
1989 if upper.contains("WHERE") && !upper.contains("ORDER") && !upper.contains("GROUP") {
1990 return (CursorContext::WhereClause, extract_partial_at_end(query));
1991 }
1992
1993 if upper.contains("FROM") && !upper.contains("WHERE") && !upper.contains("ORDER") {
1994 return (CursorContext::FromClause, extract_partial_at_end(query));
1995 }
1996
1997 if upper.contains("SELECT") && !upper.contains("FROM") {
1998 return (CursorContext::SelectClause, extract_partial_at_end(query));
1999 }
2000
2001 (CursorContext::Unknown, None)
2002}
2003
2004fn extract_partial_at_end(query: &str) -> Option<String> {
2005 let trimmed = query.trim();
2006
2007 if let Some(last_word) = trimmed.split_whitespace().last() {
2009 if last_word.starts_with('"') && !last_word.ends_with('"') {
2010 return Some(last_word.to_string());
2012 }
2013 }
2014
2015 let last_word = trimmed.split_whitespace().last()?;
2017
2018 if last_word.chars().all(|c| c.is_alphanumeric() || c == '_') && !is_sql_keyword(last_word) {
2020 Some(last_word.to_string())
2021 } else {
2022 None
2023 }
2024}
2025
2026impl ParsePrimary for Parser {
2028 fn current_token(&self) -> &Token {
2029 &self.current_token
2030 }
2031
2032 fn advance(&mut self) {
2033 self.advance();
2034 }
2035
2036 fn consume(&mut self, expected: Token) -> Result<(), String> {
2037 self.consume(expected)
2038 }
2039
2040 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
2041 self.parse_case_expression()
2042 }
2043
2044 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
2045 self.parse_function_args()
2046 }
2047
2048 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
2049 self.parse_window_spec()
2050 }
2051
2052 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
2053 self.parse_logical_or()
2054 }
2055
2056 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2057 self.parse_comparison()
2058 }
2059
2060 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2061 self.parse_expression_list()
2062 }
2063
2064 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2065 if matches!(self.current_token, Token::With) {
2067 self.parse_with_clause_inner()
2068 } else {
2069 self.parse_select_statement_inner()
2070 }
2071 }
2072}
2073
2074impl ParseArithmetic for Parser {
2076 fn current_token(&self) -> &Token {
2077 &self.current_token
2078 }
2079
2080 fn advance(&mut self) {
2081 self.advance();
2082 }
2083
2084 fn consume(&mut self, expected: Token) -> Result<(), String> {
2085 self.consume(expected)
2086 }
2087
2088 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2089 self.parse_primary()
2090 }
2091
2092 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
2093 self.parse_multiplicative()
2094 }
2095
2096 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
2097 self.parse_method_args()
2098 }
2099}
2100
2101impl ParseComparison for Parser {
2103 fn current_token(&self) -> &Token {
2104 &self.current_token
2105 }
2106
2107 fn advance(&mut self) {
2108 self.advance();
2109 }
2110
2111 fn consume(&mut self, expected: Token) -> Result<(), String> {
2112 self.consume(expected)
2113 }
2114
2115 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2116 self.parse_primary()
2117 }
2118
2119 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
2120 self.parse_additive()
2121 }
2122
2123 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2124 self.parse_expression_list()
2125 }
2126
2127 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2128 if matches!(self.current_token, Token::With) {
2130 self.parse_with_clause_inner()
2131 } else {
2132 self.parse_select_statement_inner()
2133 }
2134 }
2135}
2136
2137impl ParseLogical for Parser {
2139 fn current_token(&self) -> &Token {
2140 &self.current_token
2141 }
2142
2143 fn advance(&mut self) {
2144 self.advance();
2145 }
2146
2147 fn consume(&mut self, expected: Token) -> Result<(), String> {
2148 self.consume(expected)
2149 }
2150
2151 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
2152 self.parse_logical_and()
2153 }
2154
2155 fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String> {
2156 self.parse_comparison()
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
2170impl ParseCase for Parser {
2172 fn current_token(&self) -> &Token {
2173 &self.current_token
2174 }
2175
2176 fn advance(&mut self) {
2177 self.advance();
2178 }
2179
2180 fn consume(&mut self, expected: Token) -> Result<(), String> {
2181 self.consume(expected)
2182 }
2183
2184 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
2185 self.parse_expression()
2186 }
2187}
2188
2189fn is_sql_keyword(word: &str) -> bool {
2190 matches!(
2191 word.to_uppercase().as_str(),
2192 "SELECT"
2193 | "FROM"
2194 | "WHERE"
2195 | "AND"
2196 | "OR"
2197 | "IN"
2198 | "ORDER"
2199 | "BY"
2200 | "GROUP"
2201 | "HAVING"
2202 | "ASC"
2203 | "DESC"
2204 | "DISTINCT"
2205 )
2206}