1pub use super::parser::ast::{
5 CTEType, Condition, DataFormat, JoinClause, JoinCondition, JoinOperator, JoinType, LogicalOp,
6 OrderByColumn, SelectItem, SelectStatement, SortDirection, SqlExpression, TableFunction,
7 TableSource, WebCTESpec, WhenBranch, WhereClause, 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 Ok(WindowSpec {
948 partition_by,
949 order_by,
950 })
951 }
952
953 fn parse_order_by_list(&mut self) -> Result<Vec<OrderByColumn>, String> {
954 let mut order_columns = Vec::new();
955
956 loop {
957 let column = match &self.current_token {
958 Token::Identifier(id) => {
959 let col = id.clone();
960 self.advance();
961 col
962 }
963 Token::QuotedIdentifier(id) => {
964 let col = id.clone();
965 self.advance();
966 col
967 }
968 Token::NumberLiteral(num) if self.columns.iter().any(|col| col == num) => {
969 let col = num.clone();
971 self.advance();
972 col
973 }
974 _ => return Err("Expected column name in ORDER BY".to_string()),
975 };
976
977 let direction = match &self.current_token {
979 Token::Asc => {
980 self.advance();
981 SortDirection::Asc
982 }
983 Token::Desc => {
984 self.advance();
985 SortDirection::Desc
986 }
987 _ => SortDirection::Asc, };
989
990 order_columns.push(OrderByColumn { column, direction });
991
992 if matches!(self.current_token, Token::Comma) {
993 self.advance();
994 } else {
995 break;
996 }
997 }
998
999 Ok(order_columns)
1000 }
1001
1002 fn parse_where_clause(&mut self) -> Result<WhereClause, String> {
1003 let expr = self.parse_expression()?;
1006
1007 if matches!(self.current_token, Token::RightParen) && self.paren_depth <= 0 {
1009 return Err(
1010 "Unexpected closing parenthesis - no matching opening parenthesis".to_string(),
1011 );
1012 }
1013
1014 let conditions = vec![Condition {
1016 expr,
1017 connector: None,
1018 }];
1019
1020 Ok(WhereClause { conditions })
1021 }
1022
1023 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
1024 let mut left = self.parse_logical_or()?;
1027
1028 left = parse_in_operator(self, left)?;
1031
1032 Ok(left)
1033 }
1034
1035 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1036 parse_comparison_expr(self)
1038 }
1039
1040 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
1041 parse_additive_expr(self)
1043 }
1044
1045 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
1046 parse_multiplicative_expr(self)
1048 }
1049
1050 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1051 parse_logical_or_expr(self)
1053 }
1054
1055 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
1056 parse_logical_and_expr(self)
1058 }
1059
1060 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1061 parse_case_expr(self)
1063 }
1064
1065 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
1066 let columns = self.columns.clone();
1069 let in_method_args = self.in_method_args;
1070 let ctx = PrimaryExpressionContext {
1071 columns: &columns,
1072 in_method_args,
1073 };
1074 parse_primary_expr(self, &ctx)
1075 }
1076
1077 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
1079 let mut args = Vec::new();
1080
1081 self.in_method_args = true;
1083
1084 if !matches!(self.current_token, Token::RightParen) {
1085 loop {
1086 args.push(self.parse_expression()?);
1087
1088 if matches!(self.current_token, Token::Comma) {
1089 self.advance();
1090 } else {
1091 break;
1092 }
1093 }
1094 }
1095
1096 self.in_method_args = false;
1098
1099 Ok(args)
1100 }
1101
1102 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1103 let mut args = Vec::new();
1104 let mut has_distinct = false;
1105
1106 if !matches!(self.current_token, Token::RightParen) {
1107 if matches!(self.current_token, Token::Distinct) {
1109 self.advance(); has_distinct = true;
1111 }
1112
1113 args.push(self.parse_additive()?);
1115
1116 while matches!(self.current_token, Token::Comma) {
1118 self.advance();
1119 args.push(self.parse_additive()?);
1120 }
1121 }
1122
1123 Ok((args, has_distinct))
1124 }
1125
1126 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1127 let mut expressions = Vec::new();
1128
1129 loop {
1130 expressions.push(self.parse_expression()?);
1131
1132 if matches!(self.current_token, Token::Comma) {
1133 self.advance();
1134 } else {
1135 break;
1136 }
1137 }
1138
1139 Ok(expressions)
1140 }
1141
1142 fn get_binary_op(&self) -> Option<String> {
1143 match &self.current_token {
1144 Token::Equal => Some("=".to_string()),
1145 Token::NotEqual => Some("!=".to_string()),
1146 Token::LessThan => Some("<".to_string()),
1147 Token::GreaterThan => Some(">".to_string()),
1148 Token::LessThanOrEqual => Some("<=".to_string()),
1149 Token::GreaterThanOrEqual => Some(">=".to_string()),
1150 Token::Like => Some("LIKE".to_string()),
1151 _ => None,
1152 }
1153 }
1154
1155 fn get_arithmetic_op(&self) -> Option<String> {
1156 match &self.current_token {
1157 Token::Plus => Some("+".to_string()),
1158 Token::Minus => Some("-".to_string()),
1159 Token::Star => Some("*".to_string()), Token::Divide => Some("/".to_string()),
1161 Token::Modulo => Some("%".to_string()),
1162 _ => None,
1163 }
1164 }
1165
1166 #[must_use]
1167 pub fn get_position(&self) -> usize {
1168 self.lexer.get_position()
1169 }
1170
1171 fn is_join_token(&self) -> bool {
1173 matches!(
1174 self.current_token,
1175 Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
1176 )
1177 }
1178
1179 fn parse_join_clause(&mut self) -> Result<JoinClause, String> {
1181 let join_type = match &self.current_token {
1183 Token::Join => {
1184 self.advance();
1185 JoinType::Inner }
1187 Token::Inner => {
1188 self.advance();
1189 if !matches!(self.current_token, Token::Join) {
1190 return Err("Expected JOIN after INNER".to_string());
1191 }
1192 self.advance();
1193 JoinType::Inner
1194 }
1195 Token::Left => {
1196 self.advance();
1197 if matches!(self.current_token, Token::Outer) {
1199 self.advance();
1200 }
1201 if !matches!(self.current_token, Token::Join) {
1202 return Err("Expected JOIN after LEFT".to_string());
1203 }
1204 self.advance();
1205 JoinType::Left
1206 }
1207 Token::Right => {
1208 self.advance();
1209 if matches!(self.current_token, Token::Outer) {
1211 self.advance();
1212 }
1213 if !matches!(self.current_token, Token::Join) {
1214 return Err("Expected JOIN after RIGHT".to_string());
1215 }
1216 self.advance();
1217 JoinType::Right
1218 }
1219 Token::Full => {
1220 self.advance();
1221 if matches!(self.current_token, Token::Outer) {
1223 self.advance();
1224 }
1225 if !matches!(self.current_token, Token::Join) {
1226 return Err("Expected JOIN after FULL".to_string());
1227 }
1228 self.advance();
1229 JoinType::Full
1230 }
1231 Token::Cross => {
1232 self.advance();
1233 if !matches!(self.current_token, Token::Join) {
1234 return Err("Expected JOIN after CROSS".to_string());
1235 }
1236 self.advance();
1237 JoinType::Cross
1238 }
1239 _ => return Err("Expected JOIN keyword".to_string()),
1240 };
1241
1242 let (table, alias) = self.parse_join_table_source()?;
1244
1245 let condition = if join_type == JoinType::Cross {
1247 JoinCondition {
1249 left_column: String::new(),
1250 operator: JoinOperator::Equal,
1251 right_column: String::new(),
1252 }
1253 } else {
1254 if !matches!(self.current_token, Token::On) {
1255 return Err("Expected ON keyword after JOIN table".to_string());
1256 }
1257 self.advance();
1258 self.parse_join_condition()?
1259 };
1260
1261 Ok(JoinClause {
1262 join_type,
1263 table,
1264 alias,
1265 condition,
1266 })
1267 }
1268
1269 fn parse_join_table_source(&mut self) -> Result<(TableSource, Option<String>), String> {
1270 let table = match &self.current_token {
1271 Token::Identifier(name) => {
1272 let table_name = name.clone();
1273 self.advance();
1274 TableSource::Table(table_name)
1275 }
1276 Token::LeftParen => {
1277 self.advance();
1279 let subquery = self.parse_select_statement_inner()?;
1280 if !matches!(self.current_token, Token::RightParen) {
1281 return Err("Expected ')' after subquery".to_string());
1282 }
1283 self.advance();
1284
1285 let alias = match &self.current_token {
1287 Token::Identifier(alias_name) => {
1288 let alias = alias_name.clone();
1289 self.advance();
1290 alias
1291 }
1292 Token::As => {
1293 self.advance();
1294 match &self.current_token {
1295 Token::Identifier(alias_name) => {
1296 let alias = alias_name.clone();
1297 self.advance();
1298 alias
1299 }
1300 _ => return Err("Expected alias after AS keyword".to_string()),
1301 }
1302 }
1303 _ => return Err("Subqueries must have an alias".to_string()),
1304 };
1305
1306 return Ok((
1307 TableSource::DerivedTable {
1308 query: Box::new(subquery),
1309 alias: alias.clone(),
1310 },
1311 Some(alias),
1312 ));
1313 }
1314 _ => return Err("Expected table name or subquery in JOIN clause".to_string()),
1315 };
1316
1317 let alias = match &self.current_token {
1319 Token::Identifier(alias_name) => {
1320 let alias = alias_name.clone();
1321 self.advance();
1322 Some(alias)
1323 }
1324 Token::As => {
1325 self.advance();
1326 match &self.current_token {
1327 Token::Identifier(alias_name) => {
1328 let alias = alias_name.clone();
1329 self.advance();
1330 Some(alias)
1331 }
1332 _ => return Err("Expected alias after AS keyword".to_string()),
1333 }
1334 }
1335 _ => None,
1336 };
1337
1338 Ok((table, alias))
1339 }
1340
1341 fn parse_join_condition(&mut self) -> Result<JoinCondition, String> {
1342 let left_column = self.parse_column_reference()?;
1344
1345 let operator = match &self.current_token {
1347 Token::Equal => JoinOperator::Equal,
1348 Token::NotEqual => JoinOperator::NotEqual,
1349 Token::LessThan => JoinOperator::LessThan,
1350 Token::LessThanOrEqual => JoinOperator::LessThanOrEqual,
1351 Token::GreaterThan => JoinOperator::GreaterThan,
1352 Token::GreaterThanOrEqual => JoinOperator::GreaterThanOrEqual,
1353 _ => return Err("Expected comparison operator in JOIN condition".to_string()),
1354 };
1355 self.advance();
1356
1357 let right_column = self.parse_column_reference()?;
1359
1360 Ok(JoinCondition {
1361 left_column,
1362 operator,
1363 right_column,
1364 })
1365 }
1366
1367 fn parse_column_reference(&mut self) -> Result<String, String> {
1368 match &self.current_token {
1369 Token::Identifier(name) => {
1370 let mut column_ref = name.clone();
1371 self.advance();
1372
1373 if matches!(self.current_token, Token::Dot) {
1375 self.advance();
1376 match &self.current_token {
1377 Token::Identifier(col_name) => {
1378 column_ref.push('.');
1379 column_ref.push_str(col_name);
1380 self.advance();
1381 }
1382 _ => return Err("Expected column name after '.'".to_string()),
1383 }
1384 }
1385
1386 Ok(column_ref)
1387 }
1388 _ => Err("Expected column reference".to_string()),
1389 }
1390 }
1391}
1392
1393#[derive(Debug, Clone)]
1395pub enum CursorContext {
1396 SelectClause,
1397 FromClause,
1398 WhereClause,
1399 OrderByClause,
1400 AfterColumn(String),
1401 AfterLogicalOp(LogicalOp),
1402 AfterComparisonOp(String, String), InMethodCall(String, String), InExpression,
1405 Unknown,
1406}
1407
1408fn safe_slice_to(s: &str, pos: usize) -> &str {
1410 if pos >= s.len() {
1411 return s;
1412 }
1413
1414 let mut safe_pos = pos;
1416 while safe_pos > 0 && !s.is_char_boundary(safe_pos) {
1417 safe_pos -= 1;
1418 }
1419
1420 &s[..safe_pos]
1421}
1422
1423fn safe_slice_from(s: &str, pos: usize) -> &str {
1425 if pos >= s.len() {
1426 return "";
1427 }
1428
1429 let mut safe_pos = pos;
1431 while safe_pos < s.len() && !s.is_char_boundary(safe_pos) {
1432 safe_pos += 1;
1433 }
1434
1435 &s[safe_pos..]
1436}
1437
1438#[must_use]
1439pub fn detect_cursor_context(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1440 let truncated = safe_slice_to(query, cursor_pos);
1441 let mut parser = Parser::new(truncated);
1442
1443 if let Ok(stmt) = parser.parse() {
1445 let (ctx, partial) = analyze_statement(&stmt, truncated, cursor_pos);
1446 #[cfg(test)]
1447 println!("analyze_statement returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1448 (ctx, partial)
1449 } else {
1450 let (ctx, partial) = analyze_partial(truncated, cursor_pos);
1452 #[cfg(test)]
1453 println!("analyze_partial returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1454 (ctx, partial)
1455 }
1456}
1457
1458#[must_use]
1459pub fn tokenize_query(query: &str) -> Vec<String> {
1460 let mut lexer = Lexer::new(query);
1461 let tokens = lexer.tokenize_all();
1462 tokens.iter().map(|t| format!("{t:?}")).collect()
1463}
1464
1465#[must_use]
1466fn analyze_statement(
1467 stmt: &SelectStatement,
1468 query: &str,
1469 _cursor_pos: usize,
1470) -> (CursorContext, Option<String>) {
1471 let trimmed = query.trim();
1473
1474 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1476 for op in &comparison_ops {
1477 if let Some(op_pos) = query.rfind(op) {
1478 let before_op = safe_slice_to(query, op_pos);
1479 let after_op_start = op_pos + op.len();
1480 let after_op = if after_op_start < query.len() {
1481 &query[after_op_start..]
1482 } else {
1483 ""
1484 };
1485
1486 if let Some(col_name) = before_op.split_whitespace().last() {
1488 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1489 let after_op_trimmed = after_op.trim();
1491 if after_op_trimmed.is_empty()
1492 || (after_op_trimmed
1493 .chars()
1494 .all(|c| c.is_alphanumeric() || c == '_')
1495 && !after_op_trimmed.contains('('))
1496 {
1497 let partial = if after_op_trimmed.is_empty() {
1498 None
1499 } else {
1500 Some(after_op_trimmed.to_string())
1501 };
1502 return (
1503 CursorContext::AfterComparisonOp(
1504 col_name.to_string(),
1505 op.trim().to_string(),
1506 ),
1507 partial,
1508 );
1509 }
1510 }
1511 }
1512 }
1513 }
1514
1515 if trimmed.to_uppercase().ends_with(" AND")
1517 || trimmed.to_uppercase().ends_with(" OR")
1518 || trimmed.to_uppercase().ends_with(" AND ")
1519 || trimmed.to_uppercase().ends_with(" OR ")
1520 {
1521 } else {
1523 if let Some(dot_pos) = trimmed.rfind('.') {
1525 let before_dot = safe_slice_to(trimmed, dot_pos);
1527 let after_dot_start = dot_pos + 1;
1528 let after_dot = if after_dot_start < trimmed.len() {
1529 &trimmed[after_dot_start..]
1530 } else {
1531 ""
1532 };
1533
1534 if !after_dot.contains('(') {
1537 let col_name = if before_dot.ends_with('"') {
1539 let bytes = before_dot.as_bytes();
1541 let mut pos = before_dot.len() - 1; let mut found_start = None;
1543
1544 if pos > 0 {
1546 pos -= 1;
1547 while pos > 0 {
1548 if bytes[pos] == b'"' {
1549 if pos == 0 || bytes[pos - 1] != b'\\' {
1551 found_start = Some(pos);
1552 break;
1553 }
1554 }
1555 pos -= 1;
1556 }
1557 if found_start.is_none() && bytes[0] == b'"' {
1559 found_start = Some(0);
1560 }
1561 }
1562
1563 found_start.map(|start| safe_slice_from(before_dot, start))
1564 } else {
1565 before_dot
1568 .split_whitespace()
1569 .last()
1570 .map(|word| word.trim_start_matches('('))
1571 };
1572
1573 if let Some(col_name) = col_name {
1574 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1576 true
1578 } else {
1579 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1581 };
1582
1583 if is_valid {
1584 let partial_method = if after_dot.is_empty() {
1587 None
1588 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1589 Some(after_dot.to_string())
1590 } else {
1591 None
1592 };
1593
1594 let col_name_for_context = if col_name.starts_with('"')
1596 && col_name.ends_with('"')
1597 && col_name.len() > 2
1598 {
1599 col_name[1..col_name.len() - 1].to_string()
1600 } else {
1601 col_name.to_string()
1602 };
1603
1604 return (
1605 CursorContext::AfterColumn(col_name_for_context),
1606 partial_method,
1607 );
1608 }
1609 }
1610 }
1611 }
1612 }
1613
1614 if let Some(where_clause) = &stmt.where_clause {
1616 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1618 let op = if trimmed.to_uppercase().ends_with(" AND") {
1619 LogicalOp::And
1620 } else {
1621 LogicalOp::Or
1622 };
1623 return (CursorContext::AfterLogicalOp(op), None);
1624 }
1625
1626 if let Some(and_pos) = query.to_uppercase().rfind(" AND ") {
1628 let after_and = safe_slice_from(query, and_pos + 5);
1629 let partial = extract_partial_at_end(after_and);
1630 if partial.is_some() {
1631 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1632 }
1633 }
1634
1635 if let Some(or_pos) = query.to_uppercase().rfind(" OR ") {
1636 let after_or = safe_slice_from(query, or_pos + 4);
1637 let partial = extract_partial_at_end(after_or);
1638 if partial.is_some() {
1639 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1640 }
1641 }
1642
1643 if let Some(last_condition) = where_clause.conditions.last() {
1644 if let Some(connector) = &last_condition.connector {
1645 return (
1647 CursorContext::AfterLogicalOp(connector.clone()),
1648 extract_partial_at_end(query),
1649 );
1650 }
1651 }
1652 return (CursorContext::WhereClause, extract_partial_at_end(query));
1654 }
1655
1656 if query.to_uppercase().ends_with(" ORDER BY ") || query.to_uppercase().ends_with(" ORDER BY") {
1658 return (CursorContext::OrderByClause, None);
1659 }
1660
1661 if stmt.order_by.is_some() {
1663 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1664 }
1665
1666 if stmt.from_table.is_some() && stmt.where_clause.is_none() && stmt.order_by.is_none() {
1667 return (CursorContext::FromClause, extract_partial_at_end(query));
1668 }
1669
1670 if !stmt.columns.is_empty() && stmt.from_table.is_none() {
1671 return (CursorContext::SelectClause, extract_partial_at_end(query));
1672 }
1673
1674 (CursorContext::Unknown, None)
1675}
1676
1677fn analyze_partial(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1678 let upper = query.to_uppercase();
1679
1680 let trimmed = query.trim();
1682
1683 #[cfg(test)]
1684 {
1685 if trimmed.contains("\"Last Name\"") {
1686 eprintln!("DEBUG analyze_partial: query='{query}', trimmed='{trimmed}'");
1687 }
1688 }
1689
1690 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1692 for op in &comparison_ops {
1693 if let Some(op_pos) = query.rfind(op) {
1694 let before_op = safe_slice_to(query, op_pos);
1695 let after_op_start = op_pos + op.len();
1696 let after_op = if after_op_start < query.len() {
1697 &query[after_op_start..]
1698 } else {
1699 ""
1700 };
1701
1702 if let Some(col_name) = before_op.split_whitespace().last() {
1704 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1705 let after_op_trimmed = after_op.trim();
1707 if after_op_trimmed.is_empty()
1708 || (after_op_trimmed
1709 .chars()
1710 .all(|c| c.is_alphanumeric() || c == '_')
1711 && !after_op_trimmed.contains('('))
1712 {
1713 let partial = if after_op_trimmed.is_empty() {
1714 None
1715 } else {
1716 Some(after_op_trimmed.to_string())
1717 };
1718 return (
1719 CursorContext::AfterComparisonOp(
1720 col_name.to_string(),
1721 op.trim().to_string(),
1722 ),
1723 partial,
1724 );
1725 }
1726 }
1727 }
1728 }
1729 }
1730
1731 if let Some(dot_pos) = trimmed.rfind('.') {
1734 #[cfg(test)]
1735 {
1736 if trimmed.contains("\"Last Name\"") {
1737 eprintln!("DEBUG: Found dot at position {dot_pos}");
1738 }
1739 }
1740 let before_dot = &trimmed[..dot_pos];
1742 let after_dot = &trimmed[dot_pos + 1..];
1743
1744 if !after_dot.contains('(') {
1747 let col_name = if before_dot.ends_with('"') {
1750 let bytes = before_dot.as_bytes();
1752 let mut pos = before_dot.len() - 1; let mut found_start = None;
1754
1755 #[cfg(test)]
1756 {
1757 if trimmed.contains("\"Last Name\"") {
1758 eprintln!("DEBUG: before_dot='{before_dot}', looking for opening quote");
1759 }
1760 }
1761
1762 if pos > 0 {
1764 pos -= 1;
1765 while pos > 0 {
1766 if bytes[pos] == b'"' {
1767 if pos == 0 || bytes[pos - 1] != b'\\' {
1769 found_start = Some(pos);
1770 break;
1771 }
1772 }
1773 pos -= 1;
1774 }
1775 if found_start.is_none() && bytes[0] == b'"' {
1777 found_start = Some(0);
1778 }
1779 }
1780
1781 if let Some(start) = found_start {
1782 let result = safe_slice_from(before_dot, start);
1784 #[cfg(test)]
1785 {
1786 if trimmed.contains("\"Last Name\"") {
1787 eprintln!("DEBUG: Extracted quoted identifier: '{result}'");
1788 }
1789 }
1790 Some(result)
1791 } else {
1792 #[cfg(test)]
1793 {
1794 if trimmed.contains("\"Last Name\"") {
1795 eprintln!("DEBUG: No opening quote found!");
1796 }
1797 }
1798 None
1799 }
1800 } else {
1801 before_dot
1804 .split_whitespace()
1805 .last()
1806 .map(|word| word.trim_start_matches('('))
1807 };
1808
1809 if let Some(col_name) = col_name {
1810 #[cfg(test)]
1811 {
1812 if trimmed.contains("\"Last Name\"") {
1813 eprintln!("DEBUG: col_name = '{col_name}'");
1814 }
1815 }
1816
1817 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1819 true
1821 } else {
1822 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1824 };
1825
1826 #[cfg(test)]
1827 {
1828 if trimmed.contains("\"Last Name\"") {
1829 eprintln!("DEBUG: is_valid = {is_valid}");
1830 }
1831 }
1832
1833 if is_valid {
1834 let partial_method = if after_dot.is_empty() {
1837 None
1838 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1839 Some(after_dot.to_string())
1840 } else {
1841 None
1842 };
1843
1844 let col_name_for_context = if col_name.starts_with('"')
1846 && col_name.ends_with('"')
1847 && col_name.len() > 2
1848 {
1849 col_name[1..col_name.len() - 1].to_string()
1850 } else {
1851 col_name.to_string()
1852 };
1853
1854 return (
1855 CursorContext::AfterColumn(col_name_for_context),
1856 partial_method,
1857 );
1858 }
1859 }
1860 }
1861 }
1862
1863 if let Some(and_pos) = upper.rfind(" AND ") {
1865 if cursor_pos >= and_pos + 5 {
1867 let after_and = safe_slice_from(query, and_pos + 5);
1869 let partial = extract_partial_at_end(after_and);
1870 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1871 }
1872 }
1873
1874 if let Some(or_pos) = upper.rfind(" OR ") {
1875 if cursor_pos >= or_pos + 4 {
1877 let after_or = safe_slice_from(query, or_pos + 4);
1879 let partial = extract_partial_at_end(after_or);
1880 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1881 }
1882 }
1883
1884 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1886 let op = if trimmed.to_uppercase().ends_with(" AND") {
1887 LogicalOp::And
1888 } else {
1889 LogicalOp::Or
1890 };
1891 return (CursorContext::AfterLogicalOp(op), None);
1892 }
1893
1894 if upper.ends_with(" ORDER BY ") || upper.ends_with(" ORDER BY") || upper.contains("ORDER BY ")
1896 {
1897 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1898 }
1899
1900 if upper.contains("WHERE") && !upper.contains("ORDER") && !upper.contains("GROUP") {
1901 return (CursorContext::WhereClause, extract_partial_at_end(query));
1902 }
1903
1904 if upper.contains("FROM") && !upper.contains("WHERE") && !upper.contains("ORDER") {
1905 return (CursorContext::FromClause, extract_partial_at_end(query));
1906 }
1907
1908 if upper.contains("SELECT") && !upper.contains("FROM") {
1909 return (CursorContext::SelectClause, extract_partial_at_end(query));
1910 }
1911
1912 (CursorContext::Unknown, None)
1913}
1914
1915fn extract_partial_at_end(query: &str) -> Option<String> {
1916 let trimmed = query.trim();
1917
1918 if let Some(last_word) = trimmed.split_whitespace().last() {
1920 if last_word.starts_with('"') && !last_word.ends_with('"') {
1921 return Some(last_word.to_string());
1923 }
1924 }
1925
1926 let last_word = trimmed.split_whitespace().last()?;
1928
1929 if last_word.chars().all(|c| c.is_alphanumeric() || c == '_') && !is_sql_keyword(last_word) {
1931 Some(last_word.to_string())
1932 } else {
1933 None
1934 }
1935}
1936
1937impl ParsePrimary for Parser {
1939 fn current_token(&self) -> &Token {
1940 &self.current_token
1941 }
1942
1943 fn advance(&mut self) {
1944 self.advance();
1945 }
1946
1947 fn consume(&mut self, expected: Token) -> Result<(), String> {
1948 self.consume(expected)
1949 }
1950
1951 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1952 self.parse_case_expression()
1953 }
1954
1955 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1956 self.parse_function_args()
1957 }
1958
1959 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
1960 self.parse_window_spec()
1961 }
1962
1963 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1964 self.parse_logical_or()
1965 }
1966
1967 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1968 self.parse_comparison()
1969 }
1970
1971 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1972 self.parse_expression_list()
1973 }
1974
1975 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
1976 if matches!(self.current_token, Token::With) {
1978 self.parse_with_clause_inner()
1979 } else {
1980 self.parse_select_statement_inner()
1981 }
1982 }
1983}
1984
1985impl ParseArithmetic for Parser {
1987 fn current_token(&self) -> &Token {
1988 &self.current_token
1989 }
1990
1991 fn advance(&mut self) {
1992 self.advance();
1993 }
1994
1995 fn consume(&mut self, expected: Token) -> Result<(), String> {
1996 self.consume(expected)
1997 }
1998
1999 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2000 self.parse_primary()
2001 }
2002
2003 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
2004 self.parse_multiplicative()
2005 }
2006
2007 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
2008 self.parse_method_args()
2009 }
2010}
2011
2012impl ParseComparison for Parser {
2014 fn current_token(&self) -> &Token {
2015 &self.current_token
2016 }
2017
2018 fn advance(&mut self) {
2019 self.advance();
2020 }
2021
2022 fn consume(&mut self, expected: Token) -> Result<(), String> {
2023 self.consume(expected)
2024 }
2025
2026 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2027 self.parse_primary()
2028 }
2029
2030 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
2031 self.parse_additive()
2032 }
2033
2034 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2035 self.parse_expression_list()
2036 }
2037
2038 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2039 if matches!(self.current_token, Token::With) {
2041 self.parse_with_clause_inner()
2042 } else {
2043 self.parse_select_statement_inner()
2044 }
2045 }
2046}
2047
2048impl ParseLogical for Parser {
2050 fn current_token(&self) -> &Token {
2051 &self.current_token
2052 }
2053
2054 fn advance(&mut self) {
2055 self.advance();
2056 }
2057
2058 fn consume(&mut self, expected: Token) -> Result<(), String> {
2059 self.consume(expected)
2060 }
2061
2062 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
2063 self.parse_logical_and()
2064 }
2065
2066 fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String> {
2067 self.parse_comparison()
2070 }
2071
2072 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2073 self.parse_comparison()
2074 }
2075
2076 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2077 self.parse_expression_list()
2078 }
2079}
2080
2081impl ParseCase for Parser {
2083 fn current_token(&self) -> &Token {
2084 &self.current_token
2085 }
2086
2087 fn advance(&mut self) {
2088 self.advance();
2089 }
2090
2091 fn consume(&mut self, expected: Token) -> Result<(), String> {
2092 self.consume(expected)
2093 }
2094
2095 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
2096 self.parse_expression()
2097 }
2098}
2099
2100fn is_sql_keyword(word: &str) -> bool {
2101 matches!(
2102 word.to_uppercase().as_str(),
2103 "SELECT"
2104 | "FROM"
2105 | "WHERE"
2106 | "AND"
2107 | "OR"
2108 | "IN"
2109 | "ORDER"
2110 | "BY"
2111 | "GROUP"
2112 | "HAVING"
2113 | "ASC"
2114 | "DESC"
2115 | "DISTINCT"
2116 )
2117}