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" {
501 self.advance();
502 self.consume(Token::LeftParen)?;
504
505 let start = self.parse_expression()?;
507 self.consume(Token::Comma)?;
508
509 let end = self.parse_expression()?;
511
512 let step = if matches!(self.current_token, Token::Comma) {
514 self.advance();
515 Some(self.parse_expression()?)
516 } else {
517 None
518 };
519
520 self.consume(Token::RightParen)?;
521
522 let alias = if matches!(self.current_token, Token::As) {
524 self.advance();
525 match &self.current_token {
526 Token::Identifier(name) => {
527 let alias = name.clone();
528 self.advance();
529 Some(alias)
530 }
531 _ => return Err("Expected alias name after AS".to_string()),
532 }
533 } else if let Token::Identifier(name) = &self.current_token {
534 let alias = name.clone();
535 self.advance();
536 Some(alias)
537 } else {
538 None
539 };
540
541 (
542 None,
543 None,
544 Some(TableFunction::Range { start, end, step }),
545 alias,
546 )
547 } else if name.to_uppercase() == "SPLIT" {
548 self.advance(); self.consume(Token::LeftParen)?;
551
552 let text = self.parse_expression()?;
553
554 let delimiter = if matches!(self.current_token, Token::Comma) {
555 self.advance();
556 Some(self.parse_expression()?)
557 } else {
558 None
559 };
560
561 self.consume(Token::RightParen)?;
562
563 let alias = if matches!(self.current_token, Token::As) {
565 self.advance();
566 match &self.current_token {
567 Token::Identifier(name) => {
568 let alias = name.clone();
569 self.advance();
570 Some(alias)
571 }
572 _ => return Err("Expected alias name after AS".to_string()),
573 }
574 } else if let Token::Identifier(name) = &self.current_token {
575 let alias = name.clone();
576 self.advance();
577 Some(alias)
578 } else {
579 None
580 };
581
582 (
583 None,
584 None,
585 Some(TableFunction::Split { text, delimiter }),
586 alias,
587 )
588 } else if name.to_uppercase().starts_with("GENERATE_")
589 || name.to_uppercase().starts_with("RANDOM_")
590 || name.to_uppercase() == "FIBONACCI"
591 || name.to_uppercase() == "PRIME_FACTORS"
592 || name.to_uppercase() == "COLLATZ"
593 || name.to_uppercase() == "PASCAL_TRIANGLE"
594 || name.to_uppercase() == "TRIANGULAR"
595 || name.to_uppercase() == "SQUARES"
596 || name.to_uppercase() == "FACTORIALS"
597 {
598 let generator_name = name.clone();
600 self.advance(); self.consume(Token::LeftParen)?;
604 let mut args = Vec::new();
605
606 if !matches!(self.current_token, Token::RightParen) {
607 loop {
608 args.push(self.parse_expression()?);
609
610 if matches!(self.current_token, Token::Comma) {
611 self.advance();
612 } else {
613 break;
614 }
615 }
616 }
617
618 self.consume(Token::RightParen)?;
619
620 let alias = if matches!(self.current_token, Token::As) {
622 self.advance();
623 match &self.current_token {
624 Token::Identifier(name) => {
625 let alias = name.clone();
626 self.advance();
627 Some(alias)
628 }
629 _ => return Err("Expected alias name after AS".to_string()),
630 }
631 } else if let Token::Identifier(name) = &self.current_token {
632 let alias = name.clone();
633 self.advance();
634 Some(alias)
635 } else {
636 None
637 };
638
639 (
640 None,
641 None,
642 Some(TableFunction::Generator {
643 name: generator_name,
644 args,
645 }),
646 alias,
647 )
648 } else {
649 let table_name = name.clone();
651 self.advance();
652
653 let alias = if matches!(self.current_token, Token::As) {
655 self.advance();
656 match &self.current_token {
657 Token::Identifier(name) => {
658 let alias = name.clone();
659 self.advance();
660 Some(alias)
661 }
662 _ => return Err("Expected alias name after AS".to_string()),
663 }
664 } else if let Token::Identifier(name) = &self.current_token {
665 let alias = name.clone();
667 self.advance();
668 Some(alias)
669 } else {
670 None
671 };
672
673 (Some(table_name), None, None, alias)
674 }
675 } else if matches!(self.current_token, Token::LeftParen) {
676 self.advance();
678
679 let subquery = if matches!(self.current_token, Token::With) {
681 self.parse_with_clause_inner()?
682 } else {
683 self.parse_select_statement_inner()?
684 };
685
686 self.consume(Token::RightParen)?;
687
688 let alias = if matches!(self.current_token, Token::As) {
690 self.advance();
691 match &self.current_token {
692 Token::Identifier(name) => {
693 let alias = name.clone();
694 self.advance();
695 alias
696 }
697 _ => return Err("Expected alias name after AS".to_string()),
698 }
699 } else {
700 match &self.current_token {
702 Token::Identifier(name) => {
703 let alias = name.clone();
704 self.advance();
705 alias
706 }
707 _ => {
708 return Err(
709 "Subquery in FROM must have an alias (e.g., AS t)".to_string()
710 )
711 }
712 }
713 };
714
715 (None, Some(Box::new(subquery)), None, Some(alias))
716 } else {
717 match &self.current_token {
719 Token::Identifier(table) => {
720 let table_name = table.clone();
721 self.advance();
722
723 let alias = if matches!(self.current_token, Token::As) {
725 self.advance();
726 match &self.current_token {
727 Token::Identifier(name) => {
728 let alias = name.clone();
729 self.advance();
730 Some(alias)
731 }
732 _ => return Err("Expected alias name after AS".to_string()),
733 }
734 } else if let Token::Identifier(name) = &self.current_token {
735 let alias = name.clone();
737 self.advance();
738 Some(alias)
739 } else {
740 None
741 };
742
743 (Some(table_name), None, None, alias)
744 }
745 Token::QuotedIdentifier(table) => {
746 let table_name = table.clone();
748 self.advance();
749
750 let alias = if matches!(self.current_token, Token::As) {
752 self.advance();
753 match &self.current_token {
754 Token::Identifier(name) => {
755 let alias = name.clone();
756 self.advance();
757 Some(alias)
758 }
759 _ => return Err("Expected alias name after AS".to_string()),
760 }
761 } else if let Token::Identifier(name) = &self.current_token {
762 let alias = name.clone();
764 self.advance();
765 Some(alias)
766 } else {
767 None
768 };
769
770 (Some(table_name), None, None, alias)
771 }
772 _ => return Err("Expected table name or subquery after FROM".to_string()),
773 }
774 }
775 } else {
776 (None, None, None, None)
777 };
778
779 let mut joins = Vec::new();
781 while self.is_join_token() {
782 joins.push(self.parse_join_clause()?);
783 }
784
785 let where_clause = if matches!(self.current_token, Token::Where) {
786 self.advance();
787 Some(self.parse_where_clause()?)
788 } else {
789 None
790 };
791
792 let group_by = if matches!(self.current_token, Token::GroupBy) {
793 self.advance();
794 Some(self.parse_expression_list()?)
797 } else {
798 None
799 };
800
801 let having = if matches!(self.current_token, Token::Having) {
803 if group_by.is_none() {
804 return Err("HAVING clause requires GROUP BY".to_string());
805 }
806 self.advance();
807 Some(self.parse_expression()?)
808 } else {
809 None
810 };
811
812 let order_by = if matches!(self.current_token, Token::OrderBy) {
814 self.advance();
815 Some(self.parse_order_by_list()?)
816 } else if let Token::Identifier(s) = &self.current_token {
817 if s.to_uppercase() == "ORDER" {
818 self.advance(); if matches!(&self.current_token, Token::Identifier(by_token) if by_token.to_uppercase() == "BY")
821 {
822 self.advance(); Some(self.parse_order_by_list()?)
824 } else {
825 return Err("Expected BY after ORDER".to_string());
826 }
827 } else {
828 None
829 }
830 } else {
831 None
832 };
833
834 let limit = if matches!(self.current_token, Token::Limit) {
836 self.advance();
837 match &self.current_token {
838 Token::NumberLiteral(num) => {
839 let limit_val = num
840 .parse::<usize>()
841 .map_err(|_| format!("Invalid LIMIT value: {num}"))?;
842 self.advance();
843 Some(limit_val)
844 }
845 _ => return Err("Expected number after LIMIT".to_string()),
846 }
847 } else {
848 None
849 };
850
851 let offset = if matches!(self.current_token, Token::Offset) {
853 self.advance();
854 match &self.current_token {
855 Token::NumberLiteral(num) => {
856 let offset_val = num
857 .parse::<usize>()
858 .map_err(|_| format!("Invalid OFFSET value: {num}"))?;
859 self.advance();
860 Some(offset_val)
861 }
862 _ => return Err("Expected number after OFFSET".to_string()),
863 }
864 } else {
865 None
866 };
867
868 Ok(SelectStatement {
869 distinct,
870 columns,
871 select_items,
872 from_table,
873 from_subquery,
874 from_function,
875 from_alias,
876 joins,
877 where_clause,
878 order_by,
879 group_by,
880 having,
881 limit,
882 offset,
883 ctes: Vec::new(), })
885 }
886
887 fn parse_select_list(&mut self) -> Result<Vec<String>, String> {
888 let mut columns = Vec::new();
889
890 if matches!(self.current_token, Token::Star) {
891 columns.push("*".to_string());
892 self.advance();
893 } else {
894 loop {
895 match &self.current_token {
896 Token::Identifier(col) => {
897 columns.push(col.clone());
898 self.advance();
899 }
900 Token::QuotedIdentifier(col) => {
901 columns.push(col.clone());
903 self.advance();
904 }
905 _ => return Err("Expected column name".to_string()),
906 }
907
908 if matches!(self.current_token, Token::Comma) {
909 self.advance();
910 } else {
911 break;
912 }
913 }
914 }
915
916 Ok(columns)
917 }
918
919 fn parse_select_items(&mut self) -> Result<Vec<SelectItem>, String> {
921 let mut items = Vec::new();
922
923 loop {
924 if matches!(self.current_token, Token::Star) {
927 items.push(SelectItem::Star);
935 self.advance();
936 } else {
937 let expr = self.parse_comparison()?; let alias = if matches!(self.current_token, Token::As) {
942 self.advance();
943 match &self.current_token {
944 Token::Identifier(alias_name) => {
945 let alias = alias_name.clone();
946 self.advance();
947 alias
948 }
949 Token::QuotedIdentifier(alias_name) => {
950 let alias = alias_name.clone();
951 self.advance();
952 alias
953 }
954 _ => return Err("Expected alias name after AS".to_string()),
955 }
956 } else {
957 match &expr {
959 SqlExpression::Column(col_ref) => col_ref.name.clone(),
960 _ => format!("expr_{}", items.len() + 1), }
962 };
963
964 let item = match expr {
966 SqlExpression::Column(col_ref) if alias == col_ref.name => {
967 SelectItem::Column(col_ref)
969 }
970 _ => {
971 SelectItem::Expression { expr, alias }
973 }
974 };
975
976 items.push(item);
977 }
978
979 if matches!(self.current_token, Token::Comma) {
981 self.advance();
982 } else {
983 break;
984 }
985 }
986
987 Ok(items)
988 }
989
990 fn parse_identifier_list(&mut self) -> Result<Vec<String>, String> {
991 let mut identifiers = Vec::new();
992
993 loop {
994 match &self.current_token {
995 Token::Identifier(id) => {
996 let id_upper = id.to_uppercase();
998 if matches!(
999 id_upper.as_str(),
1000 "ORDER" | "HAVING" | "LIMIT" | "OFFSET" | "UNION" | "INTERSECT" | "EXCEPT"
1001 ) {
1002 break;
1004 }
1005 identifiers.push(id.clone());
1006 self.advance();
1007 }
1008 Token::QuotedIdentifier(id) => {
1009 identifiers.push(id.clone());
1011 self.advance();
1012 }
1013 _ => {
1014 break;
1016 }
1017 }
1018
1019 if matches!(self.current_token, Token::Comma) {
1020 self.advance();
1021 } else {
1022 break;
1023 }
1024 }
1025
1026 if identifiers.is_empty() {
1027 return Err("Expected at least one identifier".to_string());
1028 }
1029
1030 Ok(identifiers)
1031 }
1032
1033 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
1034 let mut partition_by = Vec::new();
1035 let mut order_by = Vec::new();
1036
1037 if matches!(self.current_token, Token::Partition) {
1039 self.advance(); if !matches!(self.current_token, Token::By) {
1041 return Err("Expected BY after PARTITION".to_string());
1042 }
1043 self.advance(); partition_by = self.parse_identifier_list()?;
1047 }
1048
1049 if matches!(self.current_token, Token::OrderBy) {
1051 self.advance(); order_by = self.parse_order_by_list()?;
1053 } else if let Token::Identifier(s) = &self.current_token {
1054 if s.to_uppercase() == "ORDER" {
1055 self.advance(); if !matches!(self.current_token, Token::By) {
1058 return Err("Expected BY after ORDER".to_string());
1059 }
1060 self.advance(); order_by = self.parse_order_by_list()?;
1062 }
1063 }
1064
1065 let frame = self.parse_window_frame()?;
1067
1068 Ok(WindowSpec {
1069 partition_by,
1070 order_by,
1071 frame,
1072 })
1073 }
1074
1075 fn parse_order_by_list(&mut self) -> Result<Vec<OrderByColumn>, String> {
1076 let mut order_columns = Vec::new();
1077
1078 loop {
1079 let column = match &self.current_token {
1080 Token::Identifier(id) => {
1081 let col = id.clone();
1082 self.advance();
1083 col
1084 }
1085 Token::QuotedIdentifier(id) => {
1086 let col = id.clone();
1087 self.advance();
1088 col
1089 }
1090 Token::NumberLiteral(num) if self.columns.iter().any(|col| col == num) => {
1091 let col = num.clone();
1093 self.advance();
1094 col
1095 }
1096 _ => return Err("Expected column name in ORDER BY".to_string()),
1097 };
1098
1099 let direction = match &self.current_token {
1101 Token::Asc => {
1102 self.advance();
1103 SortDirection::Asc
1104 }
1105 Token::Desc => {
1106 self.advance();
1107 SortDirection::Desc
1108 }
1109 _ => SortDirection::Asc, };
1111
1112 order_columns.push(OrderByColumn { column, direction });
1113
1114 if matches!(self.current_token, Token::Comma) {
1115 self.advance();
1116 } else {
1117 break;
1118 }
1119 }
1120
1121 Ok(order_columns)
1122 }
1123
1124 fn parse_window_frame(&mut self) -> Result<Option<WindowFrame>, String> {
1125 let unit = match &self.current_token {
1127 Token::Identifier(id) if id.to_uppercase() == "ROWS" => {
1128 self.advance();
1129 FrameUnit::Rows
1130 }
1131 Token::Identifier(id) if id.to_uppercase() == "RANGE" => {
1132 self.advance();
1133 FrameUnit::Range
1134 }
1135 _ => return Ok(None), };
1137
1138 let (start, end) = if let Token::Between = &self.current_token {
1140 self.advance(); let start = self.parse_frame_bound()?;
1143
1144 if !matches!(&self.current_token, Token::And) {
1146 return Err("Expected AND after window frame start bound".to_string());
1147 }
1148 self.advance();
1149
1150 let end = self.parse_frame_bound()?;
1152 (start, Some(end))
1153 } else {
1154 let bound = self.parse_frame_bound()?;
1156 (bound, None)
1157 };
1158
1159 Ok(Some(WindowFrame { unit, start, end }))
1160 }
1161
1162 fn parse_frame_bound(&mut self) -> Result<FrameBound, String> {
1163 match &self.current_token {
1164 Token::Identifier(id) if id.to_uppercase() == "UNBOUNDED" => {
1165 self.advance();
1166 match &self.current_token {
1167 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1168 self.advance();
1169 Ok(FrameBound::UnboundedPreceding)
1170 }
1171 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1172 self.advance();
1173 Ok(FrameBound::UnboundedFollowing)
1174 }
1175 _ => Err("Expected PRECEDING or FOLLOWING after UNBOUNDED".to_string()),
1176 }
1177 }
1178 Token::Identifier(id) if id.to_uppercase() == "CURRENT" => {
1179 self.advance();
1180 if let Token::Identifier(id) = &self.current_token {
1181 if id.to_uppercase() == "ROW" {
1182 self.advance();
1183 return Ok(FrameBound::CurrentRow);
1184 }
1185 }
1186 Err("Expected ROW after CURRENT".to_string())
1187 }
1188 Token::NumberLiteral(num) => {
1189 let n: i64 = num
1190 .parse()
1191 .map_err(|_| "Invalid number in window frame".to_string())?;
1192 self.advance();
1193 match &self.current_token {
1194 Token::Identifier(id) if id.to_uppercase() == "PRECEDING" => {
1195 self.advance();
1196 Ok(FrameBound::Preceding(n))
1197 }
1198 Token::Identifier(id) if id.to_uppercase() == "FOLLOWING" => {
1199 self.advance();
1200 Ok(FrameBound::Following(n))
1201 }
1202 _ => Err("Expected PRECEDING or FOLLOWING after number".to_string()),
1203 }
1204 }
1205 _ => Err("Invalid window frame bound".to_string()),
1206 }
1207 }
1208
1209 fn parse_where_clause(&mut self) -> Result<WhereClause, String> {
1210 let expr = self.parse_expression()?;
1213
1214 if matches!(self.current_token, Token::RightParen) && self.paren_depth <= 0 {
1216 return Err(
1217 "Unexpected closing parenthesis - no matching opening parenthesis".to_string(),
1218 );
1219 }
1220
1221 let conditions = vec![Condition {
1223 expr,
1224 connector: None,
1225 }];
1226
1227 Ok(WhereClause { conditions })
1228 }
1229
1230 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
1231 let mut left = self.parse_logical_or()?;
1234
1235 left = parse_in_operator(self, left)?;
1238
1239 Ok(left)
1240 }
1241
1242 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
1243 parse_comparison_expr(self)
1245 }
1246
1247 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
1248 parse_additive_expr(self)
1250 }
1251
1252 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
1253 parse_multiplicative_expr(self)
1255 }
1256
1257 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
1258 parse_logical_or_expr(self)
1260 }
1261
1262 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
1263 parse_logical_and_expr(self)
1265 }
1266
1267 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
1268 parse_case_expr(self)
1270 }
1271
1272 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
1273 let columns = self.columns.clone();
1276 let in_method_args = self.in_method_args;
1277 let ctx = PrimaryExpressionContext {
1278 columns: &columns,
1279 in_method_args,
1280 };
1281 parse_primary_expr(self, &ctx)
1282 }
1283
1284 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
1286 let mut args = Vec::new();
1287
1288 self.in_method_args = true;
1290
1291 if !matches!(self.current_token, Token::RightParen) {
1292 loop {
1293 args.push(self.parse_expression()?);
1294
1295 if matches!(self.current_token, Token::Comma) {
1296 self.advance();
1297 } else {
1298 break;
1299 }
1300 }
1301 }
1302
1303 self.in_method_args = false;
1305
1306 Ok(args)
1307 }
1308
1309 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
1310 let mut args = Vec::new();
1311 let mut has_distinct = false;
1312
1313 if !matches!(self.current_token, Token::RightParen) {
1314 if matches!(self.current_token, Token::Distinct) {
1316 self.advance(); has_distinct = true;
1318 }
1319
1320 args.push(self.parse_additive()?);
1322
1323 while matches!(self.current_token, Token::Comma) {
1325 self.advance();
1326 args.push(self.parse_additive()?);
1327 }
1328 }
1329
1330 Ok((args, has_distinct))
1331 }
1332
1333 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
1334 let mut expressions = Vec::new();
1335
1336 loop {
1337 expressions.push(self.parse_expression()?);
1338
1339 if matches!(self.current_token, Token::Comma) {
1340 self.advance();
1341 } else {
1342 break;
1343 }
1344 }
1345
1346 Ok(expressions)
1347 }
1348
1349 fn get_binary_op(&self) -> Option<String> {
1350 match &self.current_token {
1351 Token::Equal => Some("=".to_string()),
1352 Token::NotEqual => Some("!=".to_string()),
1353 Token::LessThan => Some("<".to_string()),
1354 Token::GreaterThan => Some(">".to_string()),
1355 Token::LessThanOrEqual => Some("<=".to_string()),
1356 Token::GreaterThanOrEqual => Some(">=".to_string()),
1357 Token::Like => Some("LIKE".to_string()),
1358 _ => None,
1359 }
1360 }
1361
1362 fn get_arithmetic_op(&self) -> Option<String> {
1363 match &self.current_token {
1364 Token::Plus => Some("+".to_string()),
1365 Token::Minus => Some("-".to_string()),
1366 Token::Star => Some("*".to_string()), Token::Divide => Some("/".to_string()),
1368 Token::Modulo => Some("%".to_string()),
1369 _ => None,
1370 }
1371 }
1372
1373 #[must_use]
1374 pub fn get_position(&self) -> usize {
1375 self.lexer.get_position()
1376 }
1377
1378 fn is_join_token(&self) -> bool {
1380 matches!(
1381 self.current_token,
1382 Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
1383 )
1384 }
1385
1386 fn parse_join_clause(&mut self) -> Result<JoinClause, String> {
1388 let join_type = match &self.current_token {
1390 Token::Join => {
1391 self.advance();
1392 JoinType::Inner }
1394 Token::Inner => {
1395 self.advance();
1396 if !matches!(self.current_token, Token::Join) {
1397 return Err("Expected JOIN after INNER".to_string());
1398 }
1399 self.advance();
1400 JoinType::Inner
1401 }
1402 Token::Left => {
1403 self.advance();
1404 if matches!(self.current_token, Token::Outer) {
1406 self.advance();
1407 }
1408 if !matches!(self.current_token, Token::Join) {
1409 return Err("Expected JOIN after LEFT".to_string());
1410 }
1411 self.advance();
1412 JoinType::Left
1413 }
1414 Token::Right => {
1415 self.advance();
1416 if matches!(self.current_token, Token::Outer) {
1418 self.advance();
1419 }
1420 if !matches!(self.current_token, Token::Join) {
1421 return Err("Expected JOIN after RIGHT".to_string());
1422 }
1423 self.advance();
1424 JoinType::Right
1425 }
1426 Token::Full => {
1427 self.advance();
1428 if matches!(self.current_token, Token::Outer) {
1430 self.advance();
1431 }
1432 if !matches!(self.current_token, Token::Join) {
1433 return Err("Expected JOIN after FULL".to_string());
1434 }
1435 self.advance();
1436 JoinType::Full
1437 }
1438 Token::Cross => {
1439 self.advance();
1440 if !matches!(self.current_token, Token::Join) {
1441 return Err("Expected JOIN after CROSS".to_string());
1442 }
1443 self.advance();
1444 JoinType::Cross
1445 }
1446 _ => return Err("Expected JOIN keyword".to_string()),
1447 };
1448
1449 let (table, alias) = self.parse_join_table_source()?;
1451
1452 let condition = if join_type == JoinType::Cross {
1454 JoinCondition {
1456 left_column: String::new(),
1457 operator: JoinOperator::Equal,
1458 right_column: String::new(),
1459 }
1460 } else {
1461 if !matches!(self.current_token, Token::On) {
1462 return Err("Expected ON keyword after JOIN table".to_string());
1463 }
1464 self.advance();
1465 self.parse_join_condition()?
1466 };
1467
1468 Ok(JoinClause {
1469 join_type,
1470 table,
1471 alias,
1472 condition,
1473 })
1474 }
1475
1476 fn parse_join_table_source(&mut self) -> Result<(TableSource, Option<String>), String> {
1477 let table = match &self.current_token {
1478 Token::Identifier(name) => {
1479 let table_name = name.clone();
1480 self.advance();
1481 TableSource::Table(table_name)
1482 }
1483 Token::LeftParen => {
1484 self.advance();
1486 let subquery = self.parse_select_statement_inner()?;
1487 if !matches!(self.current_token, Token::RightParen) {
1488 return Err("Expected ')' after subquery".to_string());
1489 }
1490 self.advance();
1491
1492 let alias = match &self.current_token {
1494 Token::Identifier(alias_name) => {
1495 let alias = alias_name.clone();
1496 self.advance();
1497 alias
1498 }
1499 Token::As => {
1500 self.advance();
1501 match &self.current_token {
1502 Token::Identifier(alias_name) => {
1503 let alias = alias_name.clone();
1504 self.advance();
1505 alias
1506 }
1507 _ => return Err("Expected alias after AS keyword".to_string()),
1508 }
1509 }
1510 _ => return Err("Subqueries must have an alias".to_string()),
1511 };
1512
1513 return Ok((
1514 TableSource::DerivedTable {
1515 query: Box::new(subquery),
1516 alias: alias.clone(),
1517 },
1518 Some(alias),
1519 ));
1520 }
1521 _ => return Err("Expected table name or subquery in JOIN clause".to_string()),
1522 };
1523
1524 let alias = match &self.current_token {
1526 Token::Identifier(alias_name) => {
1527 let alias = alias_name.clone();
1528 self.advance();
1529 Some(alias)
1530 }
1531 Token::As => {
1532 self.advance();
1533 match &self.current_token {
1534 Token::Identifier(alias_name) => {
1535 let alias = alias_name.clone();
1536 self.advance();
1537 Some(alias)
1538 }
1539 _ => return Err("Expected alias after AS keyword".to_string()),
1540 }
1541 }
1542 _ => None,
1543 };
1544
1545 Ok((table, alias))
1546 }
1547
1548 fn parse_join_condition(&mut self) -> Result<JoinCondition, String> {
1549 let left_column = self.parse_column_reference()?;
1551
1552 let operator = match &self.current_token {
1554 Token::Equal => JoinOperator::Equal,
1555 Token::NotEqual => JoinOperator::NotEqual,
1556 Token::LessThan => JoinOperator::LessThan,
1557 Token::LessThanOrEqual => JoinOperator::LessThanOrEqual,
1558 Token::GreaterThan => JoinOperator::GreaterThan,
1559 Token::GreaterThanOrEqual => JoinOperator::GreaterThanOrEqual,
1560 _ => return Err("Expected comparison operator in JOIN condition".to_string()),
1561 };
1562 self.advance();
1563
1564 let right_column = self.parse_column_reference()?;
1566
1567 Ok(JoinCondition {
1568 left_column,
1569 operator,
1570 right_column,
1571 })
1572 }
1573
1574 fn parse_column_reference(&mut self) -> Result<String, String> {
1575 match &self.current_token {
1576 Token::Identifier(name) => {
1577 let mut column_ref = name.clone();
1578 self.advance();
1579
1580 if matches!(self.current_token, Token::Dot) {
1582 self.advance();
1583 match &self.current_token {
1584 Token::Identifier(col_name) => {
1585 column_ref.push('.');
1586 column_ref.push_str(col_name);
1587 self.advance();
1588 }
1589 _ => return Err("Expected column name after '.'".to_string()),
1590 }
1591 }
1592
1593 Ok(column_ref)
1594 }
1595 _ => Err("Expected column reference".to_string()),
1596 }
1597 }
1598}
1599
1600#[derive(Debug, Clone)]
1602pub enum CursorContext {
1603 SelectClause,
1604 FromClause,
1605 WhereClause,
1606 OrderByClause,
1607 AfterColumn(String),
1608 AfterLogicalOp(LogicalOp),
1609 AfterComparisonOp(String, String), InMethodCall(String, String), InExpression,
1612 Unknown,
1613}
1614
1615fn safe_slice_to(s: &str, pos: usize) -> &str {
1617 if pos >= s.len() {
1618 return s;
1619 }
1620
1621 let mut safe_pos = pos;
1623 while safe_pos > 0 && !s.is_char_boundary(safe_pos) {
1624 safe_pos -= 1;
1625 }
1626
1627 &s[..safe_pos]
1628}
1629
1630fn safe_slice_from(s: &str, pos: usize) -> &str {
1632 if pos >= s.len() {
1633 return "";
1634 }
1635
1636 let mut safe_pos = pos;
1638 while safe_pos < s.len() && !s.is_char_boundary(safe_pos) {
1639 safe_pos += 1;
1640 }
1641
1642 &s[safe_pos..]
1643}
1644
1645#[must_use]
1646pub fn detect_cursor_context(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1647 let truncated = safe_slice_to(query, cursor_pos);
1648 let mut parser = Parser::new(truncated);
1649
1650 if let Ok(stmt) = parser.parse() {
1652 let (ctx, partial) = analyze_statement(&stmt, truncated, cursor_pos);
1653 #[cfg(test)]
1654 println!("analyze_statement returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1655 (ctx, partial)
1656 } else {
1657 let (ctx, partial) = analyze_partial(truncated, cursor_pos);
1659 #[cfg(test)]
1660 println!("analyze_partial returned: {ctx:?}, {partial:?} for query: '{truncated}'");
1661 (ctx, partial)
1662 }
1663}
1664
1665#[must_use]
1666pub fn tokenize_query(query: &str) -> Vec<String> {
1667 let mut lexer = Lexer::new(query);
1668 let tokens = lexer.tokenize_all();
1669 tokens.iter().map(|t| format!("{t:?}")).collect()
1670}
1671
1672#[must_use]
1673fn analyze_statement(
1674 stmt: &SelectStatement,
1675 query: &str,
1676 _cursor_pos: usize,
1677) -> (CursorContext, Option<String>) {
1678 let trimmed = query.trim();
1680
1681 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1683 for op in &comparison_ops {
1684 if let Some(op_pos) = query.rfind(op) {
1685 let before_op = safe_slice_to(query, op_pos);
1686 let after_op_start = op_pos + op.len();
1687 let after_op = if after_op_start < query.len() {
1688 &query[after_op_start..]
1689 } else {
1690 ""
1691 };
1692
1693 if let Some(col_name) = before_op.split_whitespace().last() {
1695 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1696 let after_op_trimmed = after_op.trim();
1698 if after_op_trimmed.is_empty()
1699 || (after_op_trimmed
1700 .chars()
1701 .all(|c| c.is_alphanumeric() || c == '_')
1702 && !after_op_trimmed.contains('('))
1703 {
1704 let partial = if after_op_trimmed.is_empty() {
1705 None
1706 } else {
1707 Some(after_op_trimmed.to_string())
1708 };
1709 return (
1710 CursorContext::AfterComparisonOp(
1711 col_name.to_string(),
1712 op.trim().to_string(),
1713 ),
1714 partial,
1715 );
1716 }
1717 }
1718 }
1719 }
1720 }
1721
1722 if trimmed.to_uppercase().ends_with(" AND")
1724 || trimmed.to_uppercase().ends_with(" OR")
1725 || trimmed.to_uppercase().ends_with(" AND ")
1726 || trimmed.to_uppercase().ends_with(" OR ")
1727 {
1728 } else {
1730 if let Some(dot_pos) = trimmed.rfind('.') {
1732 let before_dot = safe_slice_to(trimmed, dot_pos);
1734 let after_dot_start = dot_pos + 1;
1735 let after_dot = if after_dot_start < trimmed.len() {
1736 &trimmed[after_dot_start..]
1737 } else {
1738 ""
1739 };
1740
1741 if !after_dot.contains('(') {
1744 let col_name = if before_dot.ends_with('"') {
1746 let bytes = before_dot.as_bytes();
1748 let mut pos = before_dot.len() - 1; let mut found_start = None;
1750
1751 if pos > 0 {
1753 pos -= 1;
1754 while pos > 0 {
1755 if bytes[pos] == b'"' {
1756 if pos == 0 || bytes[pos - 1] != b'\\' {
1758 found_start = Some(pos);
1759 break;
1760 }
1761 }
1762 pos -= 1;
1763 }
1764 if found_start.is_none() && bytes[0] == b'"' {
1766 found_start = Some(0);
1767 }
1768 }
1769
1770 found_start.map(|start| safe_slice_from(before_dot, start))
1771 } else {
1772 before_dot
1775 .split_whitespace()
1776 .last()
1777 .map(|word| word.trim_start_matches('('))
1778 };
1779
1780 if let Some(col_name) = col_name {
1781 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
1783 true
1785 } else {
1786 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
1788 };
1789
1790 if is_valid {
1791 let partial_method = if after_dot.is_empty() {
1794 None
1795 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
1796 Some(after_dot.to_string())
1797 } else {
1798 None
1799 };
1800
1801 let col_name_for_context = if col_name.starts_with('"')
1803 && col_name.ends_with('"')
1804 && col_name.len() > 2
1805 {
1806 col_name[1..col_name.len() - 1].to_string()
1807 } else {
1808 col_name.to_string()
1809 };
1810
1811 return (
1812 CursorContext::AfterColumn(col_name_for_context),
1813 partial_method,
1814 );
1815 }
1816 }
1817 }
1818 }
1819 }
1820
1821 if let Some(where_clause) = &stmt.where_clause {
1823 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
1825 let op = if trimmed.to_uppercase().ends_with(" AND") {
1826 LogicalOp::And
1827 } else {
1828 LogicalOp::Or
1829 };
1830 return (CursorContext::AfterLogicalOp(op), None);
1831 }
1832
1833 if let Some(and_pos) = query.to_uppercase().rfind(" AND ") {
1835 let after_and = safe_slice_from(query, and_pos + 5);
1836 let partial = extract_partial_at_end(after_and);
1837 if partial.is_some() {
1838 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
1839 }
1840 }
1841
1842 if let Some(or_pos) = query.to_uppercase().rfind(" OR ") {
1843 let after_or = safe_slice_from(query, or_pos + 4);
1844 let partial = extract_partial_at_end(after_or);
1845 if partial.is_some() {
1846 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
1847 }
1848 }
1849
1850 if let Some(last_condition) = where_clause.conditions.last() {
1851 if let Some(connector) = &last_condition.connector {
1852 return (
1854 CursorContext::AfterLogicalOp(connector.clone()),
1855 extract_partial_at_end(query),
1856 );
1857 }
1858 }
1859 return (CursorContext::WhereClause, extract_partial_at_end(query));
1861 }
1862
1863 if query.to_uppercase().ends_with(" ORDER BY ") || query.to_uppercase().ends_with(" ORDER BY") {
1865 return (CursorContext::OrderByClause, None);
1866 }
1867
1868 if stmt.order_by.is_some() {
1870 return (CursorContext::OrderByClause, extract_partial_at_end(query));
1871 }
1872
1873 if stmt.from_table.is_some() && stmt.where_clause.is_none() && stmt.order_by.is_none() {
1874 return (CursorContext::FromClause, extract_partial_at_end(query));
1875 }
1876
1877 if !stmt.columns.is_empty() && stmt.from_table.is_none() {
1878 return (CursorContext::SelectClause, extract_partial_at_end(query));
1879 }
1880
1881 (CursorContext::Unknown, None)
1882}
1883
1884fn analyze_partial(query: &str, cursor_pos: usize) -> (CursorContext, Option<String>) {
1885 let upper = query.to_uppercase();
1886
1887 let trimmed = query.trim();
1889
1890 #[cfg(test)]
1891 {
1892 if trimmed.contains("\"Last Name\"") {
1893 eprintln!("DEBUG analyze_partial: query='{query}', trimmed='{trimmed}'");
1894 }
1895 }
1896
1897 let comparison_ops = [" > ", " < ", " >= ", " <= ", " = ", " != "];
1899 for op in &comparison_ops {
1900 if let Some(op_pos) = query.rfind(op) {
1901 let before_op = safe_slice_to(query, op_pos);
1902 let after_op_start = op_pos + op.len();
1903 let after_op = if after_op_start < query.len() {
1904 &query[after_op_start..]
1905 } else {
1906 ""
1907 };
1908
1909 if let Some(col_name) = before_op.split_whitespace().last() {
1911 if col_name.chars().all(|c| c.is_alphanumeric() || c == '_') {
1912 let after_op_trimmed = after_op.trim();
1914 if after_op_trimmed.is_empty()
1915 || (after_op_trimmed
1916 .chars()
1917 .all(|c| c.is_alphanumeric() || c == '_')
1918 && !after_op_trimmed.contains('('))
1919 {
1920 let partial = if after_op_trimmed.is_empty() {
1921 None
1922 } else {
1923 Some(after_op_trimmed.to_string())
1924 };
1925 return (
1926 CursorContext::AfterComparisonOp(
1927 col_name.to_string(),
1928 op.trim().to_string(),
1929 ),
1930 partial,
1931 );
1932 }
1933 }
1934 }
1935 }
1936 }
1937
1938 if let Some(dot_pos) = trimmed.rfind('.') {
1941 #[cfg(test)]
1942 {
1943 if trimmed.contains("\"Last Name\"") {
1944 eprintln!("DEBUG: Found dot at position {dot_pos}");
1945 }
1946 }
1947 let before_dot = &trimmed[..dot_pos];
1949 let after_dot = &trimmed[dot_pos + 1..];
1950
1951 if !after_dot.contains('(') {
1954 let col_name = if before_dot.ends_with('"') {
1957 let bytes = before_dot.as_bytes();
1959 let mut pos = before_dot.len() - 1; let mut found_start = None;
1961
1962 #[cfg(test)]
1963 {
1964 if trimmed.contains("\"Last Name\"") {
1965 eprintln!("DEBUG: before_dot='{before_dot}', looking for opening quote");
1966 }
1967 }
1968
1969 if pos > 0 {
1971 pos -= 1;
1972 while pos > 0 {
1973 if bytes[pos] == b'"' {
1974 if pos == 0 || bytes[pos - 1] != b'\\' {
1976 found_start = Some(pos);
1977 break;
1978 }
1979 }
1980 pos -= 1;
1981 }
1982 if found_start.is_none() && bytes[0] == b'"' {
1984 found_start = Some(0);
1985 }
1986 }
1987
1988 if let Some(start) = found_start {
1989 let result = safe_slice_from(before_dot, start);
1991 #[cfg(test)]
1992 {
1993 if trimmed.contains("\"Last Name\"") {
1994 eprintln!("DEBUG: Extracted quoted identifier: '{result}'");
1995 }
1996 }
1997 Some(result)
1998 } else {
1999 #[cfg(test)]
2000 {
2001 if trimmed.contains("\"Last Name\"") {
2002 eprintln!("DEBUG: No opening quote found!");
2003 }
2004 }
2005 None
2006 }
2007 } else {
2008 before_dot
2011 .split_whitespace()
2012 .last()
2013 .map(|word| word.trim_start_matches('('))
2014 };
2015
2016 if let Some(col_name) = col_name {
2017 #[cfg(test)]
2018 {
2019 if trimmed.contains("\"Last Name\"") {
2020 eprintln!("DEBUG: col_name = '{col_name}'");
2021 }
2022 }
2023
2024 let is_valid = if col_name.starts_with('"') && col_name.ends_with('"') {
2026 true
2028 } else {
2029 col_name.chars().all(|c| c.is_alphanumeric() || c == '_')
2031 };
2032
2033 #[cfg(test)]
2034 {
2035 if trimmed.contains("\"Last Name\"") {
2036 eprintln!("DEBUG: is_valid = {is_valid}");
2037 }
2038 }
2039
2040 if is_valid {
2041 let partial_method = if after_dot.is_empty() {
2044 None
2045 } else if after_dot.chars().all(|c| c.is_alphanumeric() || c == '_') {
2046 Some(after_dot.to_string())
2047 } else {
2048 None
2049 };
2050
2051 let col_name_for_context = if col_name.starts_with('"')
2053 && col_name.ends_with('"')
2054 && col_name.len() > 2
2055 {
2056 col_name[1..col_name.len() - 1].to_string()
2057 } else {
2058 col_name.to_string()
2059 };
2060
2061 return (
2062 CursorContext::AfterColumn(col_name_for_context),
2063 partial_method,
2064 );
2065 }
2066 }
2067 }
2068 }
2069
2070 if let Some(and_pos) = upper.rfind(" AND ") {
2072 if cursor_pos >= and_pos + 5 {
2074 let after_and = safe_slice_from(query, and_pos + 5);
2076 let partial = extract_partial_at_end(after_and);
2077 return (CursorContext::AfterLogicalOp(LogicalOp::And), partial);
2078 }
2079 }
2080
2081 if let Some(or_pos) = upper.rfind(" OR ") {
2082 if cursor_pos >= or_pos + 4 {
2084 let after_or = safe_slice_from(query, or_pos + 4);
2086 let partial = extract_partial_at_end(after_or);
2087 return (CursorContext::AfterLogicalOp(LogicalOp::Or), partial);
2088 }
2089 }
2090
2091 if trimmed.to_uppercase().ends_with(" AND") || trimmed.to_uppercase().ends_with(" OR") {
2093 let op = if trimmed.to_uppercase().ends_with(" AND") {
2094 LogicalOp::And
2095 } else {
2096 LogicalOp::Or
2097 };
2098 return (CursorContext::AfterLogicalOp(op), None);
2099 }
2100
2101 if upper.ends_with(" ORDER BY ") || upper.ends_with(" ORDER BY") || upper.contains("ORDER BY ")
2103 {
2104 return (CursorContext::OrderByClause, extract_partial_at_end(query));
2105 }
2106
2107 if upper.contains("WHERE") && !upper.contains("ORDER") && !upper.contains("GROUP") {
2108 return (CursorContext::WhereClause, extract_partial_at_end(query));
2109 }
2110
2111 if upper.contains("FROM") && !upper.contains("WHERE") && !upper.contains("ORDER") {
2112 return (CursorContext::FromClause, extract_partial_at_end(query));
2113 }
2114
2115 if upper.contains("SELECT") && !upper.contains("FROM") {
2116 return (CursorContext::SelectClause, extract_partial_at_end(query));
2117 }
2118
2119 (CursorContext::Unknown, None)
2120}
2121
2122fn extract_partial_at_end(query: &str) -> Option<String> {
2123 let trimmed = query.trim();
2124
2125 if let Some(last_word) = trimmed.split_whitespace().last() {
2127 if last_word.starts_with('"') && !last_word.ends_with('"') {
2128 return Some(last_word.to_string());
2130 }
2131 }
2132
2133 let last_word = trimmed.split_whitespace().last()?;
2135
2136 if last_word.chars().all(|c| c.is_alphanumeric() || c == '_') && !is_sql_keyword(last_word) {
2138 Some(last_word.to_string())
2139 } else {
2140 None
2141 }
2142}
2143
2144impl ParsePrimary for Parser {
2146 fn current_token(&self) -> &Token {
2147 &self.current_token
2148 }
2149
2150 fn advance(&mut self) {
2151 self.advance();
2152 }
2153
2154 fn consume(&mut self, expected: Token) -> Result<(), String> {
2155 self.consume(expected)
2156 }
2157
2158 fn parse_case_expression(&mut self) -> Result<SqlExpression, String> {
2159 self.parse_case_expression()
2160 }
2161
2162 fn parse_function_args(&mut self) -> Result<(Vec<SqlExpression>, bool), String> {
2163 self.parse_function_args()
2164 }
2165
2166 fn parse_window_spec(&mut self) -> Result<WindowSpec, String> {
2167 self.parse_window_spec()
2168 }
2169
2170 fn parse_logical_or(&mut self) -> Result<SqlExpression, String> {
2171 self.parse_logical_or()
2172 }
2173
2174 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2175 self.parse_comparison()
2176 }
2177
2178 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2179 self.parse_expression_list()
2180 }
2181
2182 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2183 if matches!(self.current_token, Token::With) {
2185 self.parse_with_clause_inner()
2186 } else {
2187 self.parse_select_statement_inner()
2188 }
2189 }
2190}
2191
2192impl ExpressionParser for Parser {
2194 fn current_token(&self) -> &Token {
2195 &self.current_token
2196 }
2197
2198 fn advance(&mut self) {
2199 match &self.current_token {
2201 Token::LeftParen => self.paren_depth += 1,
2202 Token::RightParen => {
2203 self.paren_depth -= 1;
2204 }
2205 _ => {}
2206 }
2207 self.current_token = self.lexer.next_token();
2208 }
2209
2210 fn peek(&self) -> Option<&Token> {
2211 None }
2218
2219 fn is_at_end(&self) -> bool {
2220 matches!(self.current_token, Token::Eof)
2221 }
2222
2223 fn consume(&mut self, expected: Token) -> Result<(), String> {
2224 if std::mem::discriminant(&self.current_token) == std::mem::discriminant(&expected) {
2226 match &expected {
2227 Token::LeftParen => self.paren_depth += 1,
2228 Token::RightParen => {
2229 self.paren_depth -= 1;
2230 if self.paren_depth < 0 {
2231 return Err(
2232 "Unexpected closing parenthesis - no matching opening parenthesis"
2233 .to_string(),
2234 );
2235 }
2236 }
2237 _ => {}
2238 }
2239 self.current_token = self.lexer.next_token();
2240 Ok(())
2241 } else {
2242 Err(format!(
2243 "Expected {:?}, found {:?}",
2244 expected, self.current_token
2245 ))
2246 }
2247 }
2248
2249 fn parse_identifier(&mut self) -> Result<String, String> {
2250 if let Token::Identifier(id) = &self.current_token {
2251 let id = id.clone();
2252 self.advance();
2253 Ok(id)
2254 } else {
2255 Err(format!(
2256 "Expected identifier, found {:?}",
2257 self.current_token
2258 ))
2259 }
2260 }
2261}
2262
2263impl ParseArithmetic for Parser {
2265 fn current_token(&self) -> &Token {
2266 &self.current_token
2267 }
2268
2269 fn advance(&mut self) {
2270 self.advance();
2271 }
2272
2273 fn consume(&mut self, expected: Token) -> Result<(), String> {
2274 self.consume(expected)
2275 }
2276
2277 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2278 self.parse_primary()
2279 }
2280
2281 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String> {
2282 self.parse_multiplicative()
2283 }
2284
2285 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String> {
2286 self.parse_method_args()
2287 }
2288}
2289
2290impl ParseComparison for Parser {
2292 fn current_token(&self) -> &Token {
2293 &self.current_token
2294 }
2295
2296 fn advance(&mut self) {
2297 self.advance();
2298 }
2299
2300 fn consume(&mut self, expected: Token) -> Result<(), String> {
2301 self.consume(expected)
2302 }
2303
2304 fn parse_primary(&mut self) -> Result<SqlExpression, String> {
2305 self.parse_primary()
2306 }
2307
2308 fn parse_additive(&mut self) -> Result<SqlExpression, String> {
2309 self.parse_additive()
2310 }
2311
2312 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2313 self.parse_expression_list()
2314 }
2315
2316 fn parse_subquery(&mut self) -> Result<SelectStatement, String> {
2317 if matches!(self.current_token, Token::With) {
2319 self.parse_with_clause_inner()
2320 } else {
2321 self.parse_select_statement_inner()
2322 }
2323 }
2324}
2325
2326impl ParseLogical for Parser {
2328 fn current_token(&self) -> &Token {
2329 &self.current_token
2330 }
2331
2332 fn advance(&mut self) {
2333 self.advance();
2334 }
2335
2336 fn consume(&mut self, expected: Token) -> Result<(), String> {
2337 self.consume(expected)
2338 }
2339
2340 fn parse_logical_and(&mut self) -> Result<SqlExpression, String> {
2341 self.parse_logical_and()
2342 }
2343
2344 fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String> {
2345 self.parse_comparison()
2348 }
2349
2350 fn parse_comparison(&mut self) -> Result<SqlExpression, String> {
2351 self.parse_comparison()
2352 }
2353
2354 fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String> {
2355 self.parse_expression_list()
2356 }
2357}
2358
2359impl ParseCase for Parser {
2361 fn current_token(&self) -> &Token {
2362 &self.current_token
2363 }
2364
2365 fn advance(&mut self) {
2366 self.advance();
2367 }
2368
2369 fn consume(&mut self, expected: Token) -> Result<(), String> {
2370 self.consume(expected)
2371 }
2372
2373 fn parse_expression(&mut self) -> Result<SqlExpression, String> {
2374 self.parse_expression()
2375 }
2376}
2377
2378fn is_sql_keyword(word: &str) -> bool {
2379 matches!(
2380 word.to_uppercase().as_str(),
2381 "SELECT"
2382 | "FROM"
2383 | "WHERE"
2384 | "AND"
2385 | "OR"
2386 | "IN"
2387 | "ORDER"
2388 | "BY"
2389 | "GROUP"
2390 | "HAVING"
2391 | "ASC"
2392 | "DESC"
2393 | "DISTINCT"
2394 )
2395}