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(col_ref) => col_ref.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 if name.to_uppercase() == "SPLIT" {
535 self.advance(); self.consume(Token::LeftParen)?;
538
539 let text = self.parse_expression()?;
540
541 let delimiter = if matches!(self.current_token, Token::Comma) {
542 self.advance();
543 Some(self.parse_expression()?)
544 } else {
545 None
546 };
547
548 self.consume(Token::RightParen)?;
549
550 let alias = if matches!(self.current_token, Token::As) {
552 self.advance();
553 match &self.current_token {
554 Token::Identifier(name) => {
555 let alias = name.clone();
556 self.advance();
557 Some(alias)
558 }
559 _ => return Err("Expected alias name after AS".to_string()),
560 }
561 } else if let Token::Identifier(name) = &self.current_token {
562 let alias = name.clone();
563 self.advance();
564 Some(alias)
565 } else {
566 None
567 };
568
569 (
570 None,
571 None,
572 Some(TableFunction::Split { text, delimiter }),
573 alias,
574 )
575 } else if name.to_uppercase().starts_with("GENERATE_")
576 || name.to_uppercase().starts_with("RANDOM_")
577 || name.to_uppercase() == "FIBONACCI"
578 || name.to_uppercase() == "PRIME_FACTORS"
579 || name.to_uppercase() == "COLLATZ"
580 || name.to_uppercase() == "PASCAL_TRIANGLE"
581 || name.to_uppercase() == "TRIANGULAR"
582 || name.to_uppercase() == "SQUARES"
583 || name.to_uppercase() == "FACTORIALS"
584 {
585 let generator_name = name.clone();
587 self.advance(); self.consume(Token::LeftParen)?;
591 let mut args = Vec::new();
592
593 if !matches!(self.current_token, Token::RightParen) {
594 loop {
595 args.push(self.parse_expression()?);
596
597 if matches!(self.current_token, Token::Comma) {
598 self.advance();
599 } else {
600 break;
601 }
602 }
603 }
604
605 self.consume(Token::RightParen)?;
606
607 let alias = if matches!(self.current_token, Token::As) {
609 self.advance();
610 match &self.current_token {
611 Token::Identifier(name) => {
612 let alias = name.clone();
613 self.advance();
614 Some(alias)
615 }
616 _ => return Err("Expected alias name after AS".to_string()),
617 }
618 } else if let Token::Identifier(name) = &self.current_token {
619 let alias = name.clone();
620 self.advance();
621 Some(alias)
622 } else {
623 None
624 };
625
626 (
627 None,
628 None,
629 Some(TableFunction::Generator {
630 name: generator_name,
631 args,
632 }),
633 alias,
634 )
635 } else {
636 let table_name = name.clone();
638 self.advance();
639
640 let alias = if matches!(self.current_token, Token::As) {
642 self.advance();
643 match &self.current_token {
644 Token::Identifier(name) => {
645 let alias = name.clone();
646 self.advance();
647 Some(alias)
648 }
649 _ => return Err("Expected alias name after AS".to_string()),
650 }
651 } else if let Token::Identifier(name) = &self.current_token {
652 let alias = name.clone();
654 self.advance();
655 Some(alias)
656 } else {
657 None
658 };
659
660 (Some(table_name), None, None, alias)
661 }
662 } else if matches!(self.current_token, Token::LeftParen) {
663 self.advance();
665
666 let subquery = if matches!(self.current_token, Token::With) {
668 self.parse_with_clause_inner()?
669 } else {
670 self.parse_select_statement_inner()?
671 };
672
673 self.consume(Token::RightParen)?;
674
675 let alias = if matches!(self.current_token, Token::As) {
677 self.advance();
678 match &self.current_token {
679 Token::Identifier(name) => {
680 let alias = name.clone();
681 self.advance();
682 alias
683 }
684 _ => return Err("Expected alias name after AS".to_string()),
685 }
686 } else {
687 match &self.current_token {
689 Token::Identifier(name) => {
690 let alias = name.clone();
691 self.advance();
692 alias
693 }
694 _ => {
695 return Err(
696 "Subquery in FROM must have an alias (e.g., AS t)".to_string()
697 )
698 }
699 }
700 };
701
702 (None, Some(Box::new(subquery)), None, Some(alias))
703 } else {
704 match &self.current_token {
706 Token::Identifier(table) => {
707 let table_name = table.clone();
708 self.advance();
709
710 let alias = if matches!(self.current_token, Token::As) {
712 self.advance();
713 match &self.current_token {
714 Token::Identifier(name) => {
715 let alias = name.clone();
716 self.advance();
717 Some(alias)
718 }
719 _ => return Err("Expected alias name after AS".to_string()),
720 }
721 } else if let Token::Identifier(name) = &self.current_token {
722 let alias = name.clone();
724 self.advance();
725 Some(alias)
726 } else {
727 None
728 };
729
730 (Some(table_name), None, None, alias)
731 }
732 Token::QuotedIdentifier(table) => {
733 let table_name = table.clone();
735 self.advance();
736
737 let alias = if matches!(self.current_token, Token::As) {
739 self.advance();
740 match &self.current_token {
741 Token::Identifier(name) => {
742 let alias = name.clone();
743 self.advance();
744 Some(alias)
745 }
746 _ => return Err("Expected alias name after AS".to_string()),
747 }
748 } else if let Token::Identifier(name) = &self.current_token {
749 let alias = name.clone();
751 self.advance();
752 Some(alias)
753 } else {
754 None
755 };
756
757 (Some(table_name), None, None, alias)
758 }
759 _ => return Err("Expected table name or subquery after FROM".to_string()),
760 }
761 }
762 } else {
763 (None, None, None, None)
764 };
765
766 let mut joins = Vec::new();
768 while self.is_join_token() {
769 joins.push(self.parse_join_clause()?);
770 }
771
772 let where_clause = if matches!(self.current_token, Token::Where) {
773 self.advance();
774 Some(self.parse_where_clause()?)
775 } else {
776 None
777 };
778
779 let group_by = if matches!(self.current_token, Token::GroupBy) {
780 self.advance();
781 Some(self.parse_expression_list()?)
784 } else {
785 None
786 };
787
788 let having = if matches!(self.current_token, Token::Having) {
790 if group_by.is_none() {
791 return Err("HAVING clause requires GROUP BY".to_string());
792 }
793 self.advance();
794 Some(self.parse_expression()?)
795 } else {
796 None
797 };
798
799 let order_by = if matches!(self.current_token, Token::OrderBy) {
801 self.advance();
802 Some(self.parse_order_by_list()?)
803 } else if let Token::Identifier(s) = &self.current_token {
804 if s.to_uppercase() == "ORDER" {
805 self.advance(); if matches!(&self.current_token, Token::Identifier(by_token) if by_token.to_uppercase() == "BY")
808 {
809 self.advance(); Some(self.parse_order_by_list()?)
811 } else {
812 return Err("Expected BY after ORDER".to_string());
813 }
814 } else {
815 None
816 }
817 } else {
818 None
819 };
820
821 let limit = if matches!(self.current_token, Token::Limit) {
823 self.advance();
824 match &self.current_token {
825 Token::NumberLiteral(num) => {
826 let limit_val = num
827 .parse::<usize>()
828 .map_err(|_| format!("Invalid LIMIT value: {num}"))?;
829 self.advance();
830 Some(limit_val)
831 }
832 _ => return Err("Expected number after LIMIT".to_string()),
833 }
834 } else {
835 None
836 };
837
838 let offset = if matches!(self.current_token, Token::Offset) {
840 self.advance();
841 match &self.current_token {
842 Token::NumberLiteral(num) => {
843 let offset_val = num
844 .parse::<usize>()
845 .map_err(|_| format!("Invalid OFFSET value: {num}"))?;
846 self.advance();
847 Some(offset_val)
848 }
849 _ => return Err("Expected number after OFFSET".to_string()),
850 }
851 } else {
852 None
853 };
854
855 Ok(SelectStatement {
856 distinct,
857 columns,
858 select_items,
859 from_table,
860 from_subquery,
861 from_function,
862 from_alias,
863 joins,
864 where_clause,
865 order_by,
866 group_by,
867 having,
868 limit,
869 offset,
870 ctes: Vec::new(), })
872 }
873
874 fn parse_select_list(&mut self) -> Result<Vec<String>, String> {
875 let mut columns = Vec::new();
876
877 if matches!(self.current_token, Token::Star) {
878 columns.push("*".to_string());
879 self.advance();
880 } else {
881 loop {
882 match &self.current_token {
883 Token::Identifier(col) => {
884 columns.push(col.clone());
885 self.advance();
886 }
887 Token::QuotedIdentifier(col) => {
888 columns.push(col.clone());
890 self.advance();
891 }
892 _ => return Err("Expected column name".to_string()),
893 }
894
895 if matches!(self.current_token, Token::Comma) {
896 self.advance();
897 } else {
898 break;
899 }
900 }
901 }
902
903 Ok(columns)
904 }
905
906 fn parse_select_items(&mut self) -> Result<Vec<SelectItem>, String> {
908 let mut items = Vec::new();
909
910 loop {
911 if matches!(self.current_token, Token::Star) {
914 items.push(SelectItem::Star);
922 self.advance();
923 } else {
924 let expr = self.parse_comparison()?; let alias = if matches!(self.current_token, Token::As) {
929 self.advance();
930 match &self.current_token {
931 Token::Identifier(alias_name) => {
932 let alias = alias_name.clone();
933 self.advance();
934 alias
935 }
936 Token::QuotedIdentifier(alias_name) => {
937 let alias = alias_name.clone();
938 self.advance();
939 alias
940 }
941 _ => return Err("Expected alias name after AS".to_string()),
942 }
943 } else {
944 match &expr {
946 SqlExpression::Column(col_ref) => col_ref.name.clone(),
947 _ => format!("expr_{}", items.len() + 1), }
949 };
950
951 let item = match expr {
953 SqlExpression::Column(col_ref) if alias == col_ref.name => {
954 SelectItem::Column(col_ref)
956 }
957 _ => {
958 SelectItem::Expression { expr, alias }
960 }
961 };
962
963 items.push(item);
964 }
965
966 if matches!(self.current_token, Token::Comma) {
968 self.advance();
969 } else {
970 break;
971 }
972 }
973
974 Ok(items)
975 }
976
977 fn parse_identifier_list(&mut self) -> Result<Vec<String>, String> {
978 let mut identifiers = Vec::new();
979
980 loop {
981 match &self.current_token {
982 Token::Identifier(id) => {
983 let id_upper = id.to_uppercase();
985 if matches!(
986 id_upper.as_str(),
987 "ORDER" | "HAVING" | "LIMIT" | "OFFSET" | "UNION" | "INTERSECT" | "EXCEPT"
988 ) {
989 break;
991 }
992 identifiers.push(id.clone());
993 self.advance();
994 }
995 Token::QuotedIdentifier(id) => {
996 identifiers.push(id.clone());
998 self.advance();
999 }
1000 _ => {
1001 break;
1003 }
1004 }
1005
1006 if matches!(self.current_token, Token::Comma) {
1007 self.advance();
1008 } else {
1009 break;
1010 }
1011 }
1012
1013 if identifiers.is_empty() {
1014 return Err("Expected at least one identifier".to_string());
1015 }
1016
1017 Ok(identifiers)
1018 }
1019
1020 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
1021 let mut partition_by = Vec::new();
1022 let mut order_by = Vec::new();
1023
1024 if matches!(self.current_token, Token::Partition) {
1026 self.advance(); if !matches!(self.current_token, Token::By) {
1028 return Err("Expected BY after PARTITION".to_string());
1029 }
1030 self.advance(); partition_by = self.parse_identifier_list()?;
1034 }
1035
1036 if matches!(self.current_token, Token::OrderBy) {
1038 self.advance(); order_by = self.parse_order_by_list()?;
1040 } else if let Token::Identifier(s) = &self.current_token {
1041 if s.to_uppercase() == "ORDER" {
1042 self.advance(); if !matches!(self.current_token, Token::By) {
1045 return Err("Expected BY after ORDER".to_string());
1046 }
1047 self.advance(); order_by = self.parse_order_by_list()?;
1049 }
1050 }
1051
1052 let frame = self.parse_window_frame()?;
1054
1055 Ok(WindowSpec {
1056 partition_by,
1057 order_by,
1058 frame,
1059 })
1060 }
1061
1062 fn parse_order_by_list(&mut self) -> Result<Vec<OrderByColumn>, String> {
1063 let mut order_columns = Vec::new();
1064
1065 loop {
1066 let column = match &self.current_token {
1067 Token::Identifier(id) => {
1068 let col = id.clone();
1069 self.advance();
1070 col
1071 }
1072 Token::QuotedIdentifier(id) => {
1073 let col = id.clone();
1074 self.advance();
1075 col
1076 }
1077 Token::NumberLiteral(num) if self.columns.iter().any(|col| col == num) => {
1078 let col = num.clone();
1080 self.advance();
1081 col
1082 }
1083 _ => return Err("Expected column name in ORDER BY".to_string()),
1084 };
1085
1086 let direction = match &self.current_token {
1088 Token::Asc => {
1089 self.advance();
1090 SortDirection::Asc
1091 }
1092 Token::Desc => {
1093 self.advance();
1094 SortDirection::Desc
1095 }
1096 _ => SortDirection::Asc, };
1098
1099 order_columns.push(OrderByColumn { column, direction });
1100
1101 if matches!(self.current_token, Token::Comma) {
1102 self.advance();
1103 } else {
1104 break;
1105 }
1106 }
1107
1108 Ok(order_columns)
1109 }
1110
1111 fn parse_window_frame(&mut self) -> Result<Option<WindowFrame>, String> {
1112 let unit = match &self.current_token {
1114 Token::Identifier(id) if id.to_uppercase() == "ROWS" => {
1115 self.advance();
1116 FrameUnit::Rows
1117 }
1118 Token::Identifier(id) if id.to_uppercase() == "RANGE" => {
1119 self.advance();
1120 FrameUnit::Range
1121 }
1122 _ => return Ok(None), };
1124
1125 let (start, end) = if let Token::Between = &self.current_token {
1127 self.advance(); let start = self.parse_frame_bound()?;
1130
1131 if !matches!(&self.current_token, Token::And) {
1133 return Err("Expected AND after window frame start bound".to_string());
1134 }
1135 self.advance();
1136
1137 let end = self.parse_frame_bound()?;
1139 (start, Some(end))
1140 } else {
1141 let bound = self.parse_frame_bound()?;
1143 (bound, None)
1144 };
1145
1146 Ok(Some(WindowFrame { unit, start, end }))
1147 }
1148
1149 fn parse_frame_bound(&mut self) -> Result<FrameBound, String> {
1150 match &self.current_token {
1151 Token::Identifier(id) if id.to_uppercase() == "UNBOUNDED" => {
1152 self.advance();
1153 match &self.current_token {
1154 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1155 self.advance();
1156 Ok(FrameBound::UnboundedPreceding)
1157 }
1158 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1159 self.advance();
1160 Ok(FrameBound::UnboundedFollowing)
1161 }
1162 _ => Err("Expected PRECEDING or FOLLOWING after UNBOUNDED".to_string()),
1163 }
1164 }
1165 Token::Identifier(id) if id.to_uppercase() == "CURRENT" => {
1166 self.advance();
1167 if let Token::Identifier(id) = &self.current_token {
1168 if id.to_uppercase() == "ROW" {
1169 self.advance();
1170 return Ok(FrameBound::CurrentRow);
1171 }
1172 }
1173 Err("Expected ROW after CURRENT".to_string())
1174 }
1175 Token::NumberLiteral(num) => {
1176 let n: i64 = num
1177 .parse()
1178 .map_err(|_| "Invalid number in window frame".to_string())?;
1179 self.advance();
1180 match &self.current_token {
1181 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1182 self.advance();
1183 Ok(FrameBound::Preceding(n))
1184 }
1185 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1186 self.advance();
1187 Ok(FrameBound::Following(n))
1188 }
1189 _ => Err("Expected PRECEDING or FOLLOWING after number".to_string()),
1190 }
1191 }
1192 _ => Err("Invalid window frame bound".to_string()),
1193 }
1194 }
1195
1196 fn parse_where_clause(&mut self) -> Result<WhereClause, String> {
1197 let expr = self.parse_expression()?;
1200
1201 if matches!(self.current_token, Token::RightParen) && self.paren_depth <= 0 {
1203 return Err(
1204 "Unexpected closing parenthesis - no matching opening parenthesis".to_string(),
1205 );
1206 }
1207
1208 let conditions = vec![Condition {
1210 expr,
1211 connector: None,
1212 }];
1213
1214 Ok(WhereClause { conditions })
1215 }
1216
1217 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
1218 let mut left = self.parse_logical_or()?;
1221
1222 left = parse_in_operator(self, left)?;
1225
1226 Ok(left)
1227 }
1228
1229 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1230 parse_comparison_expr(self)
1232 }
1233
1234 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
1235 parse_additive_expr(self)
1237 }
1238
1239 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
1240 parse_multiplicative_expr(self)
1242 }
1243
1244 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1245 parse_logical_or_expr(self)
1247 }
1248
1249 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
1250 parse_logical_and_expr(self)
1252 }
1253
1254 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1255 parse_case_expr(self)
1257 }
1258
1259 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
1260 let columns = self.columns.clone();
1263 let in_method_args = self.in_method_args;
1264 let ctx = PrimaryExpressionContext {
1265 columns: &columns,
1266 in_method_args,
1267 };
1268 parse_primary_expr(self, &ctx)
1269 }
1270
1271 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
1273 let mut args = Vec::new();
1274
1275 self.in_method_args = true;
1277
1278 if !matches!(self.current_token, Token::RightParen) {
1279 loop {
1280 args.push(self.parse_expression()?);
1281
1282 if matches!(self.current_token, Token::Comma) {
1283 self.advance();
1284 } else {
1285 break;
1286 }
1287 }
1288 }
1289
1290 self.in_method_args = false;
1292
1293 Ok(args)
1294 }
1295
1296 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1297 let mut args = Vec::new();
1298 let mut has_distinct = false;
1299
1300 if !matches!(self.current_token, Token::RightParen) {
1301 if matches!(self.current_token, Token::Distinct) {
1303 self.advance(); has_distinct = true;
1305 }
1306
1307 args.push(self.parse_additive()?);
1309
1310 while matches!(self.current_token, Token::Comma) {
1312 self.advance();
1313 args.push(self.parse_additive()?);
1314 }
1315 }
1316
1317 Ok((args, has_distinct))
1318 }
1319
1320 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1321 let mut expressions = Vec::new();
1322
1323 loop {
1324 expressions.push(self.parse_expression()?);
1325
1326 if matches!(self.current_token, Token::Comma) {
1327 self.advance();
1328 } else {
1329 break;
1330 }
1331 }
1332
1333 Ok(expressions)
1334 }
1335
1336 fn get_binary_op(&self) -> Option<String> {
1337 match &self.current_token {
1338 Token::Equal => Some("=".to_string()),
1339 Token::NotEqual => Some("!=".to_string()),
1340 Token::LessThan => Some("<".to_string()),
1341 Token::GreaterThan => Some(">".to_string()),
1342 Token::LessThanOrEqual => Some("<=".to_string()),
1343 Token::GreaterThanOrEqual => Some(">=".to_string()),
1344 Token::Like => Some("LIKE".to_string()),
1345 _ => None,
1346 }
1347 }
1348
1349 fn get_arithmetic_op(&self) -> Option<String> {
1350 match &self.current_token {
1351 Token::Plus => Some("+".to_string()),
1352 Token::Minus => Some("-".to_string()),
1353 Token::Star => Some("*".to_string()), Token::Divide => Some("/".to_string()),
1355 Token::Modulo => Some("%".to_string()),
1356 _ => None,
1357 }
1358 }
1359
1360 #[must_use]
1361 pub fn get_position(&self) -> usize {
1362 self.lexer.get_position()
1363 }
1364
1365 fn is_join_token(&self) -> bool {
1367 matches!(
1368 self.current_token,
1369 Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
1370 )
1371 }
1372
1373 fn parse_join_clause(&mut self) -> Result<JoinClause, String> {
1375 let join_type = match &self.current_token {
1377 Token::Join => {
1378 self.advance();
1379 JoinType::Inner }
1381 Token::Inner => {
1382 self.advance();
1383 if !matches!(self.current_token, Token::Join) {
1384 return Err("Expected JOIN after INNER".to_string());
1385 }
1386 self.advance();
1387 JoinType::Inner
1388 }
1389 Token::Left => {
1390 self.advance();
1391 if matches!(self.current_token, Token::Outer) {
1393 self.advance();
1394 }
1395 if !matches!(self.current_token, Token::Join) {
1396 return Err("Expected JOIN after LEFT".to_string());
1397 }
1398 self.advance();
1399 JoinType::Left
1400 }
1401 Token::Right => {
1402 self.advance();
1403 if matches!(self.current_token, Token::Outer) {
1405 self.advance();
1406 }
1407 if !matches!(self.current_token, Token::Join) {
1408 return Err("Expected JOIN after RIGHT".to_string());
1409 }
1410 self.advance();
1411 JoinType::Right
1412 }
1413 Token::Full => {
1414 self.advance();
1415 if matches!(self.current_token, Token::Outer) {
1417 self.advance();
1418 }
1419 if !matches!(self.current_token, Token::Join) {
1420 return Err("Expected JOIN after FULL".to_string());
1421 }
1422 self.advance();
1423 JoinType::Full
1424 }
1425 Token::Cross => {
1426 self.advance();
1427 if !matches!(self.current_token, Token::Join) {
1428 return Err("Expected JOIN after CROSS".to_string());
1429 }
1430 self.advance();
1431 JoinType::Cross
1432 }
1433 _ => return Err("Expected JOIN keyword".to_string()),
1434 };
1435
1436 let (table, alias) = self.parse_join_table_source()?;
1438
1439 let condition = if join_type == JoinType::Cross {
1441 JoinCondition {
1443 left_column: String::new(),
1444 operator: JoinOperator::Equal,
1445 right_column: String::new(),
1446 }
1447 } else {
1448 if !matches!(self.current_token, Token::On) {
1449 return Err("Expected ON keyword after JOIN table".to_string());
1450 }
1451 self.advance();
1452 self.parse_join_condition()?
1453 };
1454
1455 Ok(JoinClause {
1456 join_type,
1457 table,
1458 alias,
1459 condition,
1460 })
1461 }
1462
1463 fn parse_join_table_source(&mut self) -> Result<(TableSource, Option<String>), String> {
1464 let table = match &self.current_token {
1465 Token::Identifier(name) => {
1466 let table_name = name.clone();
1467 self.advance();
1468 TableSource::Table(table_name)
1469 }
1470 Token::LeftParen => {
1471 self.advance();
1473 let subquery = self.parse_select_statement_inner()?;
1474 if !matches!(self.current_token, Token::RightParen) {
1475 return Err("Expected ')' after subquery".to_string());
1476 }
1477 self.advance();
1478
1479 let alias = match &self.current_token {
1481 Token::Identifier(alias_name) => {
1482 let alias = alias_name.clone();
1483 self.advance();
1484 alias
1485 }
1486 Token::As => {
1487 self.advance();
1488 match &self.current_token {
1489 Token::Identifier(alias_name) => {
1490 let alias = alias_name.clone();
1491 self.advance();
1492 alias
1493 }
1494 _ => return Err("Expected alias after AS keyword".to_string()),
1495 }
1496 }
1497 _ => return Err("Subqueries must have an alias".to_string()),
1498 };
1499
1500 return Ok((
1501 TableSource::DerivedTable {
1502 query: Box::new(subquery),
1503 alias: alias.clone(),
1504 },
1505 Some(alias),
1506 ));
1507 }
1508 _ => return Err("Expected table name or subquery in JOIN clause".to_string()),
1509 };
1510
1511 let alias = match &self.current_token {
1513 Token::Identifier(alias_name) => {
1514 let alias = alias_name.clone();
1515 self.advance();
1516 Some(alias)
1517 }
1518 Token::As => {
1519 self.advance();
1520 match &self.current_token {
1521 Token::Identifier(alias_name) => {
1522 let alias = alias_name.clone();
1523 self.advance();
1524 Some(alias)
1525 }
1526 _ => return Err("Expected alias after AS keyword".to_string()),
1527 }
1528 }
1529 _ => None,
1530 };
1531
1532 Ok((table, alias))
1533 }
1534
1535 fn parse_join_condition(&mut self) -> Result<JoinCondition, String> {
1536 let left_column = self.parse_column_reference()?;
1538
1539 let operator = match &self.current_token {
1541 Token::Equal => JoinOperator::Equal,
1542 Token::NotEqual => JoinOperator::NotEqual,
1543 Token::LessThan => JoinOperator::LessThan,
1544 Token::LessThanOrEqual => JoinOperator::LessThanOrEqual,
1545 Token::GreaterThan => JoinOperator::GreaterThan,
1546 Token::GreaterThanOrEqual => JoinOperator::GreaterThanOrEqual,
1547 _ => return Err("Expected comparison operator in JOIN condition".to_string()),
1548 };
1549 self.advance();
1550
1551 let right_column = self.parse_column_reference()?;
1553
1554 Ok(JoinCondition {
1555 left_column,
1556 operator,
1557 right_column,
1558 })
1559 }
1560
1561 fn parse_column_reference(&mut self) -> Result<String, String> {
1562 match &self.current_token {
1563 Token::Identifier(name) => {
1564 let mut column_ref = name.clone();
1565 self.advance();
1566
1567 if matches!(self.current_token, Token::Dot) {
1569 self.advance();
1570 match &self.current_token {
1571 Token::Identifier(col_name) => {
1572 column_ref.push('.');
1573 column_ref.push_str(col_name);
1574 self.advance();
1575 }
1576 _ => return Err("Expected column name after '.'".to_string()),
1577 }
1578 }
1579
1580 Ok(column_ref)
1581 }
1582 _ => Err("Expected column reference".to_string()),
1583 }
1584 }
1585}
1586
1587#[derive(Debug, Clone)]
1589pub enum CursorContext {
1590 SelectClause,
1591 FromClause,
1592 WhereClause,
1593 OrderByClause,
1594 AfterColumn(String),
1595 AfterLogicalOp(LogicalOp),
1596 AfterComparisonOp(String, String), InMethodCall(String, String), InExpression,
1599 Unknown,
1600}
1601
1602fn safe_slice_to(s: &str, pos: usize) -> &str {
1604 if pos >= s.len() {
1605 return s;
1606 }
1607
1608 let mut safe_pos = pos;
1610 while safe_pos > 0 && !s.is_char_boundary(safe_pos) {
1611 safe_pos -= 1;
1612 }
1613
1614 &s[..safe_pos]
1615}
1616
1617fn safe_slice_from(s: &str, pos: usize) -> &str {
1619 if pos >= s.len() {
1620 return "";
1621 }
1622
1623 let mut safe_pos = pos;
1625 while safe_pos < s.len() && !s.is_char_boundary(safe_pos) {
1626 safe_pos += 1;
1627 }
1628
1629 &s[safe_pos..]
1630}
1631
1632#[must_use]
1633pub fn detect_cursor_context(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1634 let truncated = safe_slice_to(query, cursor_pos);
1635 let mut parser = Parser::new(truncated);
1636
1637 if let Ok(stmt) = parser.parse() {
1639 let (ctx, partial) = analyze_statement(&stmt, truncated, cursor_pos);
1640 #[cfg(test)]
1641 println!("analyze_statement returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1642 (ctx, partial)
1643 } else {
1644 let (ctx, partial) = analyze_partial(truncated, cursor_pos);
1646 #[cfg(test)]
1647 println!("analyze_partial returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1648 (ctx, partial)
1649 }
1650}
1651
1652#[must_use]
1653pub fn tokenize_query(query: &str) -> Vec<String> {
1654 let mut lexer = Lexer::new(query);
1655 let tokens = lexer.tokenize_all();
1656 tokens.iter().map(|t| format!("{t:?}")).collect()
1657}
1658
1659#[must_use]
1660fn analyze_statement(
1661 stmt: &SelectStatement,
1662 query: &str,
1663 _cursor_pos: usize,
1664) -> (CursorContext, Option<String>) {
1665 let trimmed = query.trim();
1667
1668 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1670 for op in &comparison_ops {
1671 if let Some(op_pos) = query.rfind(op) {
1672 let before_op = safe_slice_to(query, op_pos);
1673 let after_op_start = op_pos + op.len();
1674 let after_op = if after_op_start < query.len() {
1675 &query[after_op_start..]
1676 } else {
1677 ""
1678 };
1679
1680 if let Some(col_name) = before_op.split_whitespace().last() {
1682 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1683 let after_op_trimmed = after_op.trim();
1685 if after_op_trimmed.is_empty()
1686 || (after_op_trimmed
1687 .chars()
1688 .all(|c| c.is_alphanumeric() || c == '_')
1689 && !after_op_trimmed.contains('('))
1690 {
1691 let partial = if after_op_trimmed.is_empty() {
1692 None
1693 } else {
1694 Some(after_op_trimmed.to_string())
1695 };
1696 return (
1697 CursorContext::AfterComparisonOp(
1698 col_name.to_string(),
1699 op.trim().to_string(),
1700 ),
1701 partial,
1702 );
1703 }
1704 }
1705 }
1706 }
1707 }
1708
1709 if trimmed.to_uppercase().ends_with(" AND")
1711 || trimmed.to_uppercase().ends_with(" OR")
1712 || trimmed.to_uppercase().ends_with(" AND ")
1713 || trimmed.to_uppercase().ends_with(" OR ")
1714 {
1715 } else {
1717 if let Some(dot_pos) = trimmed.rfind('.') {
1719 let before_dot = safe_slice_to(trimmed, dot_pos);
1721 let after_dot_start = dot_pos + 1;
1722 let after_dot = if after_dot_start < trimmed.len() {
1723 &trimmed[after_dot_start..]
1724 } else {
1725 ""
1726 };
1727
1728 if !after_dot.contains('(') {
1731 let col_name = if before_dot.ends_with('"') {
1733 let bytes = before_dot.as_bytes();
1735 let mut pos = before_dot.len() - 1; let mut found_start = None;
1737
1738 if pos > 0 {
1740 pos -= 1;
1741 while pos > 0 {
1742 if bytes[pos] == b'"' {
1743 if pos == 0 || bytes[pos - 1] != b'\\' {
1745 found_start = Some(pos);
1746 break;
1747 }
1748 }
1749 pos -= 1;
1750 }
1751 if found_start.is_none() && bytes[0] == b'"' {
1753 found_start = Some(0);
1754 }
1755 }
1756
1757 found_start.map(|start| safe_slice_from(before_dot, start))
1758 } else {
1759 before_dot
1762 .split_whitespace()
1763 .last()
1764 .map(|word| word.trim_start_matches('('))
1765 };
1766
1767 if let Some(col_name) = col_name {
1768 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1770 true
1772 } else {
1773 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1775 };
1776
1777 if is_valid {
1778 let partial_method = if after_dot.is_empty() {
1781 None
1782 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1783 Some(after_dot.to_string())
1784 } else {
1785 None
1786 };
1787
1788 let col_name_for_context = if col_name.starts_with('"')
1790 && col_name.ends_with('"')
1791 && col_name.len() > 2
1792 {
1793 col_name[1..col_name.len() - 1].to_string()
1794 } else {
1795 col_name.to_string()
1796 };
1797
1798 return (
1799 CursorContext::AfterColumn(col_name_for_context),
1800 partial_method,
1801 );
1802 }
1803 }
1804 }
1805 }
1806 }
1807
1808 if let Some(where_clause) = &stmt.where_clause {
1810 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1812 let op = if trimmed.to_uppercase().ends_with(" AND") {
1813 LogicalOp::And
1814 } else {
1815 LogicalOp::Or
1816 };
1817 return (CursorContext::AfterLogicalOp(op), None);
1818 }
1819
1820 if let Some(and_pos) = query.to_uppercase().rfind(" AND ") {
1822 let after_and = safe_slice_from(query, and_pos + 5);
1823 let partial = extract_partial_at_end(after_and);
1824 if partial.is_some() {
1825 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1826 }
1827 }
1828
1829 if let Some(or_pos) = query.to_uppercase().rfind(" OR ") {
1830 let after_or = safe_slice_from(query, or_pos + 4);
1831 let partial = extract_partial_at_end(after_or);
1832 if partial.is_some() {
1833 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1834 }
1835 }
1836
1837 if let Some(last_condition) = where_clause.conditions.last() {
1838 if let Some(connector) = &last_condition.connector {
1839 return (
1841 CursorContext::AfterLogicalOp(connector.clone()),
1842 extract_partial_at_end(query),
1843 );
1844 }
1845 }
1846 return (CursorContext::WhereClause, extract_partial_at_end(query));
1848 }
1849
1850 if query.to_uppercase().ends_with(" ORDER BY ") || query.to_uppercase().ends_with(" ORDER BY") {
1852 return (CursorContext::OrderByClause, None);
1853 }
1854
1855 if stmt.order_by.is_some() {
1857 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1858 }
1859
1860 if stmt.from_table.is_some() && stmt.where_clause.is_none() && stmt.order_by.is_none() {
1861 return (CursorContext::FromClause, extract_partial_at_end(query));
1862 }
1863
1864 if !stmt.columns.is_empty() && stmt.from_table.is_none() {
1865 return (CursorContext::SelectClause, extract_partial_at_end(query));
1866 }
1867
1868 (CursorContext::Unknown, None)
1869}
1870
1871fn analyze_partial(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1872 let upper = query.to_uppercase();
1873
1874 let trimmed = query.trim();
1876
1877 #[cfg(test)]
1878 {
1879 if trimmed.contains("\"Last Name\"") {
1880 eprintln!("DEBUG analyze_partial: query='{query}', trimmed='{trimmed}'");
1881 }
1882 }
1883
1884 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1886 for op in &comparison_ops {
1887 if let Some(op_pos) = query.rfind(op) {
1888 let before_op = safe_slice_to(query, op_pos);
1889 let after_op_start = op_pos + op.len();
1890 let after_op = if after_op_start < query.len() {
1891 &query[after_op_start..]
1892 } else {
1893 ""
1894 };
1895
1896 if let Some(col_name) = before_op.split_whitespace().last() {
1898 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1899 let after_op_trimmed = after_op.trim();
1901 if after_op_trimmed.is_empty()
1902 || (after_op_trimmed
1903 .chars()
1904 .all(|c| c.is_alphanumeric() || c == '_')
1905 && !after_op_trimmed.contains('('))
1906 {
1907 let partial = if after_op_trimmed.is_empty() {
1908 None
1909 } else {
1910 Some(after_op_trimmed.to_string())
1911 };
1912 return (
1913 CursorContext::AfterComparisonOp(
1914 col_name.to_string(),
1915 op.trim().to_string(),
1916 ),
1917 partial,
1918 );
1919 }
1920 }
1921 }
1922 }
1923 }
1924
1925 if let Some(dot_pos) = trimmed.rfind('.') {
1928 #[cfg(test)]
1929 {
1930 if trimmed.contains("\"Last Name\"") {
1931 eprintln!("DEBUG: Found dot at position {dot_pos}");
1932 }
1933 }
1934 let before_dot = &trimmed[..dot_pos];
1936 let after_dot = &trimmed[dot_pos + 1..];
1937
1938 if !after_dot.contains('(') {
1941 let col_name = if before_dot.ends_with('"') {
1944 let bytes = before_dot.as_bytes();
1946 let mut pos = before_dot.len() - 1; let mut found_start = None;
1948
1949 #[cfg(test)]
1950 {
1951 if trimmed.contains("\"Last Name\"") {
1952 eprintln!("DEBUG: before_dot='{before_dot}', looking for opening quote");
1953 }
1954 }
1955
1956 if pos > 0 {
1958 pos -= 1;
1959 while pos > 0 {
1960 if bytes[pos] == b'"' {
1961 if pos == 0 || bytes[pos - 1] != b'\\' {
1963 found_start = Some(pos);
1964 break;
1965 }
1966 }
1967 pos -= 1;
1968 }
1969 if found_start.is_none() && bytes[0] == b'"' {
1971 found_start = Some(0);
1972 }
1973 }
1974
1975 if let Some(start) = found_start {
1976 let result = safe_slice_from(before_dot, start);
1978 #[cfg(test)]
1979 {
1980 if trimmed.contains("\"Last Name\"") {
1981 eprintln!("DEBUG: Extracted quoted identifier: '{result}'");
1982 }
1983 }
1984 Some(result)
1985 } else {
1986 #[cfg(test)]
1987 {
1988 if trimmed.contains("\"Last Name\"") {
1989 eprintln!("DEBUG: No opening quote found!");
1990 }
1991 }
1992 None
1993 }
1994 } else {
1995 before_dot
1998 .split_whitespace()
1999 .last()
2000 .map(|word| word.trim_start_matches('('))
2001 };
2002
2003 if let Some(col_name) = col_name {
2004 #[cfg(test)]
2005 {
2006 if trimmed.contains("\"Last Name\"") {
2007 eprintln!("DEBUG: col_name = '{col_name}'");
2008 }
2009 }
2010
2011 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
2013 true
2015 } else {
2016 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
2018 };
2019
2020 #[cfg(test)]
2021 {
2022 if trimmed.contains("\"Last Name\"") {
2023 eprintln!("DEBUG: is_valid = {is_valid}");
2024 }
2025 }
2026
2027 if is_valid {
2028 let partial_method = if after_dot.is_empty() {
2031 None
2032 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
2033 Some(after_dot.to_string())
2034 } else {
2035 None
2036 };
2037
2038 let col_name_for_context = if col_name.starts_with('"')
2040 && col_name.ends_with('"')
2041 && col_name.len() > 2
2042 {
2043 col_name[1..col_name.len() - 1].to_string()
2044 } else {
2045 col_name.to_string()
2046 };
2047
2048 return (
2049 CursorContext::AfterColumn(col_name_for_context),
2050 partial_method,
2051 );
2052 }
2053 }
2054 }
2055 }
2056
2057 if let Some(and_pos) = upper.rfind(" AND ") {
2059 if cursor_pos >= and_pos + 5 {
2061 let after_and = safe_slice_from(query, and_pos + 5);
2063 let partial = extract_partial_at_end(after_and);
2064 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
2065 }
2066 }
2067
2068 if let Some(or_pos) = upper.rfind(" OR ") {
2069 if cursor_pos >= or_pos + 4 {
2071 let after_or = safe_slice_from(query, or_pos + 4);
2073 let partial = extract_partial_at_end(after_or);
2074 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
2075 }
2076 }
2077
2078 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
2080 let op = if trimmed.to_uppercase().ends_with(" AND") {
2081 LogicalOp::And
2082 } else {
2083 LogicalOp::Or
2084 };
2085 return (CursorContext::AfterLogicalOp(op), None);
2086 }
2087
2088 if upper.ends_with(" ORDER BY ") || upper.ends_with(" ORDER BY") || upper.contains("ORDER BY ")
2090 {
2091 return (CursorContext::OrderByClause, extract_partial_at_end(query));
2092 }
2093
2094 if upper.contains("WHERE") && !upper.contains("ORDER") && !upper.contains("GROUP") {
2095 return (CursorContext::WhereClause, extract_partial_at_end(query));
2096 }
2097
2098 if upper.contains("FROM") && !upper.contains("WHERE") && !upper.contains("ORDER") {
2099 return (CursorContext::FromClause, extract_partial_at_end(query));
2100 }
2101
2102 if upper.contains("SELECT") && !upper.contains("FROM") {
2103 return (CursorContext::SelectClause, extract_partial_at_end(query));
2104 }
2105
2106 (CursorContext::Unknown, None)
2107}
2108
2109fn extract_partial_at_end(query: &str) -> Option<String> {
2110 let trimmed = query.trim();
2111
2112 if let Some(last_word) = trimmed.split_whitespace().last() {
2114 if last_word.starts_with('"') && !last_word.ends_with('"') {
2115 return Some(last_word.to_string());
2117 }
2118 }
2119
2120 let last_word = trimmed.split_whitespace().last()?;
2122
2123 if last_word.chars().all(|c| c.is_alphanumeric() || c == '_') && !is_sql_keyword(last_word) {
2125 Some(last_word.to_string())
2126 } else {
2127 None
2128 }
2129}
2130
2131impl ParsePrimary for Parser {
2133 fn current_token(&self) -> &Token {
2134 &self.current_token
2135 }
2136
2137 fn advance(&mut self) {
2138 self.advance();
2139 }
2140
2141 fn consume(&mut self, expected: Token) -> Result<(), String> {
2142 self.consume(expected)
2143 }
2144
2145 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
2146 self.parse_case_expression()
2147 }
2148
2149 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
2150 self.parse_function_args()
2151 }
2152
2153 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
2154 self.parse_window_spec()
2155 }
2156
2157 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
2158 self.parse_logical_or()
2159 }
2160
2161 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2162 self.parse_comparison()
2163 }
2164
2165 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2166 self.parse_expression_list()
2167 }
2168
2169 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2170 if matches!(self.current_token, Token::With) {
2172 self.parse_with_clause_inner()
2173 } else {
2174 self.parse_select_statement_inner()
2175 }
2176 }
2177}
2178
2179impl ParseArithmetic for Parser {
2181 fn current_token(&self) -> &Token {
2182 &self.current_token
2183 }
2184
2185 fn advance(&mut self) {
2186 self.advance();
2187 }
2188
2189 fn consume(&mut self, expected: Token) -> Result<(), String> {
2190 self.consume(expected)
2191 }
2192
2193 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2194 self.parse_primary()
2195 }
2196
2197 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
2198 self.parse_multiplicative()
2199 }
2200
2201 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
2202 self.parse_method_args()
2203 }
2204}
2205
2206impl ParseComparison for Parser {
2208 fn current_token(&self) -> &Token {
2209 &self.current_token
2210 }
2211
2212 fn advance(&mut self) {
2213 self.advance();
2214 }
2215
2216 fn consume(&mut self, expected: Token) -> Result<(), String> {
2217 self.consume(expected)
2218 }
2219
2220 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2221 self.parse_primary()
2222 }
2223
2224 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
2225 self.parse_additive()
2226 }
2227
2228 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2229 self.parse_expression_list()
2230 }
2231
2232 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2233 if matches!(self.current_token, Token::With) {
2235 self.parse_with_clause_inner()
2236 } else {
2237 self.parse_select_statement_inner()
2238 }
2239 }
2240}
2241
2242impl ParseLogical for Parser {
2244 fn current_token(&self) -> &Token {
2245 &self.current_token
2246 }
2247
2248 fn advance(&mut self) {
2249 self.advance();
2250 }
2251
2252 fn consume(&mut self, expected: Token) -> Result<(), String> {
2253 self.consume(expected)
2254 }
2255
2256 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
2257 self.parse_logical_and()
2258 }
2259
2260 fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String> {
2261 self.parse_comparison()
2264 }
2265
2266 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2267 self.parse_comparison()
2268 }
2269
2270 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2271 self.parse_expression_list()
2272 }
2273}
2274
2275impl ParseCase for Parser {
2277 fn current_token(&self) -> &Token {
2278 &self.current_token
2279 }
2280
2281 fn advance(&mut self) {
2282 self.advance();
2283 }
2284
2285 fn consume(&mut self, expected: Token) -> Result<(), String> {
2286 self.consume(expected)
2287 }
2288
2289 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
2290 self.parse_expression()
2291 }
2292}
2293
2294fn is_sql_keyword(word: &str) -> bool {
2295 matches!(
2296 word.to_uppercase().as_str(),
2297 "SELECT"
2298 | "FROM"
2299 | "WHERE"
2300 | "AND"
2301 | "OR"
2302 | "IN"
2303 | "ORDER"
2304 | "BY"
2305 | "GROUP"
2306 | "HAVING"
2307 | "ASC"
2308 | "DESC"
2309 | "DISTINCT"
2310 )
2311}