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