1use crate::sql::parser::ast::*;
8use std::fmt::Write;
9
10pub struct FormatConfig {
12 pub indent: String,
14 pub items_per_line: usize,
16 pub uppercase_keywords: bool,
18 pub compact: bool,
20}
21
22impl Default for FormatConfig {
23 fn default() -> Self {
24 Self {
25 indent: " ".to_string(),
26 items_per_line: 5,
27 uppercase_keywords: true,
28 compact: false,
29 }
30 }
31}
32
33pub fn format_select_statement(stmt: &SelectStatement) -> String {
35 format_select_with_config(stmt, &FormatConfig::default())
36}
37
38pub fn format_select_with_config(stmt: &SelectStatement, config: &FormatConfig) -> String {
40 let formatter = AstFormatter::new(config);
41 formatter.format_select(stmt, 0)
42}
43
44pub fn format_expression(expr: &SqlExpression) -> String {
47 let config = FormatConfig::default();
48 let formatter = AstFormatter::new(&config);
49 formatter.format_expression(expr)
50}
51
52struct AstFormatter<'a> {
53 config: &'a FormatConfig,
54}
55
56impl<'a> AstFormatter<'a> {
57 fn new(config: &'a FormatConfig) -> Self {
58 Self { config }
59 }
60
61 fn keyword(&self, word: &str) -> String {
62 if self.config.uppercase_keywords {
63 word.to_uppercase()
64 } else {
65 word.to_lowercase()
66 }
67 }
68
69 fn indent(&self, level: usize) -> String {
70 self.config.indent.repeat(level)
71 }
72
73 fn format_select(&self, stmt: &SelectStatement, indent_level: usize) -> String {
74 let mut result = String::new();
75 let indent = self.indent(indent_level);
76
77 if !stmt.ctes.is_empty() {
79 writeln!(&mut result, "{}{}", indent, self.keyword("WITH")).unwrap();
80 for (i, cte) in stmt.ctes.iter().enumerate() {
81 let is_last = i == stmt.ctes.len() - 1;
82 self.format_cte(&mut result, cte, indent_level + 1, is_last);
83 }
84 }
85
86 write!(&mut result, "{}{}", indent, self.keyword("SELECT")).unwrap();
88 if stmt.distinct {
89 write!(&mut result, " {}", self.keyword("DISTINCT")).unwrap();
90 }
91
92 if stmt.select_items.is_empty() && !stmt.columns.is_empty() {
94 self.format_column_list(&mut result, &stmt.columns, indent_level);
96 } else {
97 self.format_select_items(&mut result, &stmt.select_items, indent_level);
98 }
99
100 if let Some(ref table) = stmt.from_table {
102 writeln!(&mut result).unwrap();
103 write!(&mut result, "{}{} {}", indent, self.keyword("FROM"), table).unwrap();
104 } else if let Some(ref subquery) = stmt.from_subquery {
105 writeln!(&mut result).unwrap();
106 write!(&mut result, "{}{} (", indent, self.keyword("FROM")).unwrap();
107 writeln!(&mut result).unwrap();
108 let subquery_sql = self.format_select(subquery, indent_level + 1);
109 write!(&mut result, "{}", subquery_sql).unwrap();
110 write!(&mut result, "\n{}", indent).unwrap();
111 write!(&mut result, ")").unwrap();
112 if let Some(ref alias) = stmt.from_alias {
113 write!(&mut result, " {} {}", self.keyword("AS"), alias).unwrap();
114 }
115 } else if let Some(ref func) = stmt.from_function {
116 writeln!(&mut result).unwrap();
117 write!(&mut result, "{}{} ", indent, self.keyword("FROM")).unwrap();
118 self.format_table_function(&mut result, func);
119 if let Some(ref alias) = stmt.from_alias {
120 write!(&mut result, " {} {}", self.keyword("AS"), alias).unwrap();
121 }
122 }
123
124 for join in &stmt.joins {
126 writeln!(&mut result).unwrap();
127 self.format_join(&mut result, join, indent_level);
128 }
129
130 if let Some(ref where_clause) = stmt.where_clause {
132 writeln!(&mut result).unwrap();
133 write!(&mut result, "{}{}", indent, self.keyword("WHERE")).unwrap();
134 self.format_where_clause(&mut result, where_clause, indent_level);
135 }
136
137 if let Some(ref group_by) = stmt.group_by {
139 writeln!(&mut result).unwrap();
140 write!(&mut result, "{}{} ", indent, self.keyword("GROUP BY")).unwrap();
141 for (i, expr) in group_by.iter().enumerate() {
142 if i > 0 {
143 write!(&mut result, ", ").unwrap();
144 }
145 write!(&mut result, "{}", self.format_expression(expr)).unwrap();
146 }
147 }
148
149 if let Some(ref having) = stmt.having {
151 writeln!(&mut result).unwrap();
152 write!(
153 &mut result,
154 "{}{} {}",
155 indent,
156 self.keyword("HAVING"),
157 self.format_expression(having)
158 )
159 .unwrap();
160 }
161
162 if let Some(ref order_by) = stmt.order_by {
164 writeln!(&mut result).unwrap();
165 write!(&mut result, "{}{} ", indent, self.keyword("ORDER BY")).unwrap();
166 for (i, col) in order_by.iter().enumerate() {
167 if i > 0 {
168 write!(&mut result, ", ").unwrap();
169 }
170 write!(&mut result, "{}", col.column).unwrap();
171 match col.direction {
172 SortDirection::Asc => write!(&mut result, " {}", self.keyword("ASC")).unwrap(),
173 SortDirection::Desc => {
174 write!(&mut result, " {}", self.keyword("DESC")).unwrap()
175 }
176 }
177 }
178 }
179
180 if let Some(limit) = stmt.limit {
182 writeln!(&mut result).unwrap();
183 write!(&mut result, "{}{} {}", indent, self.keyword("LIMIT"), limit).unwrap();
184 }
185
186 if let Some(offset) = stmt.offset {
188 writeln!(&mut result).unwrap();
189 write!(
190 &mut result,
191 "{}{} {}",
192 indent,
193 self.keyword("OFFSET"),
194 offset
195 )
196 .unwrap();
197 }
198
199 result
200 }
201
202 fn format_cte(&self, result: &mut String, cte: &CTE, indent_level: usize, is_last: bool) {
203 let indent = self.indent(indent_level);
204
205 let is_web = matches!(&cte.cte_type, crate::sql::parser::ast::CTEType::Web(_));
207 if is_web {
208 write!(result, "{}{} {}", indent, self.keyword("WEB"), cte.name).unwrap();
209 } else {
210 write!(result, "{}{}", indent, cte.name).unwrap();
211 }
212
213 if let Some(ref columns) = cte.column_list {
214 write!(result, "(").unwrap();
215 for (i, col) in columns.iter().enumerate() {
216 if i > 0 {
217 write!(result, ", ").unwrap();
218 }
219 write!(result, "{}", col).unwrap();
220 }
221 write!(result, ")").unwrap();
222 }
223
224 writeln!(result, " {} (", self.keyword("AS")).unwrap();
225 let cte_sql = match &cte.cte_type {
226 crate::sql::parser::ast::CTEType::Standard(query) => {
227 self.format_select(query, indent_level + 1)
228 }
229 crate::sql::parser::ast::CTEType::Web(web_spec) => {
230 let mut web_str = format!(
232 "{}{} '{}'",
233 " ".repeat(indent_level + 1),
234 self.keyword("URL"),
235 web_spec.url
236 );
237
238 if let Some(method) = &web_spec.method {
240 web_str.push_str(&format!(
241 " {} {}",
242 self.keyword("METHOD"),
243 match method {
244 crate::sql::parser::ast::HttpMethod::GET => "GET",
245 crate::sql::parser::ast::HttpMethod::POST => "POST",
246 crate::sql::parser::ast::HttpMethod::PUT => "PUT",
247 crate::sql::parser::ast::HttpMethod::DELETE => "DELETE",
248 crate::sql::parser::ast::HttpMethod::PATCH => "PATCH",
249 }
250 ));
251 }
252
253 if let Some(body) = &web_spec.body {
255 let trimmed_body = body.trim();
257 if (trimmed_body.starts_with('{') && trimmed_body.ends_with('}'))
258 || (trimmed_body.starts_with('[') && trimmed_body.ends_with(']'))
259 {
260 match serde_json::from_str::<serde_json::Value>(trimmed_body) {
262 Ok(json_val) => {
263 match serde_json::to_string_pretty(&json_val) {
265 Ok(pretty_json) => {
266 let is_complex = pretty_json.lines().count() > 1
268 || pretty_json.contains('"')
269 || pretty_json.contains('\\');
270
271 if is_complex {
272 let base_indent = " ".repeat(indent_level + 1);
274 let json_lines: Vec<String> = pretty_json
275 .lines()
276 .enumerate()
277 .map(|(i, line)| {
278 if i == 0 {
279 line.to_string()
280 } else {
281 format!("{}{}", base_indent, line)
282 }
283 })
284 .collect();
285 let formatted_json = json_lines.join("\n");
286
287 web_str.push_str(&format!(
288 " {} $JSON${}\n{}$JSON$\n{}",
289 self.keyword("BODY"),
290 formatted_json,
291 base_indent,
292 base_indent
293 ));
294 } else {
295 web_str.push_str(&format!(
297 " {} '{}'",
298 self.keyword("BODY"),
299 pretty_json
300 ));
301 }
302 }
303 Err(_) => {
304 web_str.push_str(&format!(
306 " {} '{}'",
307 self.keyword("BODY"),
308 body
309 ));
310 }
311 }
312 }
313 Err(_) => {
314 web_str.push_str(&format!(" {} '{}'", self.keyword("BODY"), body));
316 }
317 }
318 } else {
319 web_str.push_str(&format!(" {} '{}'", self.keyword("BODY"), body));
321 }
322 }
323
324 if let Some(format) = &web_spec.format {
326 web_str.push_str(&format!(
327 " {} {}",
328 self.keyword("FORMAT"),
329 match format {
330 crate::sql::parser::ast::DataFormat::CSV => "CSV",
331 crate::sql::parser::ast::DataFormat::JSON => "JSON",
332 crate::sql::parser::ast::DataFormat::Auto => "AUTO",
333 }
334 ));
335 }
336
337 if let Some(json_path) = &web_spec.json_path {
339 web_str.push_str(&format!(" {} '{}'", self.keyword("JSON_PATH"), json_path));
340 }
341
342 if let Some(cache) = web_spec.cache_seconds {
344 web_str.push_str(&format!(" {} {}", self.keyword("CACHE"), cache));
345 }
346
347 for (field_name, file_path) in &web_spec.form_files {
349 web_str.push_str(&format!(
350 "\n{}{} '{}' '{}'",
351 " ".repeat(indent_level + 1),
352 self.keyword("FORM_FILE"),
353 field_name,
354 file_path
355 ));
356 }
357
358 for (field_name, value) in &web_spec.form_fields {
360 let trimmed_value = value.trim();
362 if (trimmed_value.starts_with('{') && trimmed_value.ends_with('}'))
363 || (trimmed_value.starts_with('[') && trimmed_value.ends_with(']'))
364 {
365 match serde_json::from_str::<serde_json::Value>(trimmed_value) {
367 Ok(json_val) => {
368 match serde_json::to_string_pretty(&json_val) {
370 Ok(pretty_json) => {
371 let is_complex = pretty_json.lines().count() > 1
373 || pretty_json.contains('"')
374 || pretty_json.contains('\\');
375
376 if is_complex {
377 let base_indent = " ".repeat(indent_level + 1);
379 let json_lines: Vec<String> = pretty_json
380 .lines()
381 .enumerate()
382 .map(|(i, line)| {
383 if i == 0 {
384 line.to_string()
385 } else {
386 format!("{}{}", base_indent, line)
387 }
388 })
389 .collect();
390 let formatted_json = json_lines.join("\n");
391
392 web_str.push_str(&format!(
393 "\n{}{} '{}' $JSON${}\n{}$JSON$",
394 base_indent,
395 self.keyword("FORM_FIELD"),
396 field_name,
397 formatted_json,
398 base_indent
399 ));
400 } else {
401 web_str.push_str(&format!(
403 "\n{}{} '{}' '{}'",
404 " ".repeat(indent_level + 1),
405 self.keyword("FORM_FIELD"),
406 field_name,
407 pretty_json
408 ));
409 }
410 }
411 Err(_) => {
412 web_str.push_str(&format!(
414 "\n{}{} '{}' '{}'",
415 " ".repeat(indent_level + 1),
416 self.keyword("FORM_FIELD"),
417 field_name,
418 value
419 ));
420 }
421 }
422 }
423 Err(_) => {
424 web_str.push_str(&format!(
426 "\n{}{} '{}' '{}'",
427 " ".repeat(indent_level + 1),
428 self.keyword("FORM_FIELD"),
429 field_name,
430 value
431 ));
432 }
433 }
434 } else {
435 web_str.push_str(&format!(
437 "\n{}{} '{}' '{}'",
438 " ".repeat(indent_level + 1),
439 self.keyword("FORM_FIELD"),
440 field_name,
441 value
442 ));
443 }
444 }
445
446 if !web_spec.headers.is_empty() {
448 web_str.push_str(&format!(" {} (", self.keyword("HEADERS")));
449 for (i, (key, value)) in web_spec.headers.iter().enumerate() {
450 if i > 0 {
451 web_str.push_str(", ");
452 }
453 web_str.push_str(&format!("'{}': '{}'", key, value));
454 }
455 web_str.push(')');
456 }
457
458 web_str
459 }
460 };
461 write!(result, "{}", cte_sql).unwrap();
462 writeln!(result).unwrap();
463 write!(result, "{}", indent).unwrap();
464 if is_last {
465 writeln!(result, ")").unwrap();
466 } else {
467 writeln!(result, "),").unwrap();
468 }
469 }
470
471 fn format_column_list(&self, result: &mut String, columns: &[String], indent_level: usize) {
472 if columns.len() <= self.config.items_per_line {
473 write!(result, " ").unwrap();
475 for (i, col) in columns.iter().enumerate() {
476 if i > 0 {
477 write!(result, ", ").unwrap();
478 }
479 write!(result, "{}", col).unwrap();
480 }
481 } else {
482 writeln!(result).unwrap();
484 let indent = self.indent(indent_level + 1);
485 for (i, col) in columns.iter().enumerate() {
486 write!(result, "{}{}", indent, col).unwrap();
487 if i < columns.len() - 1 {
488 writeln!(result, ",").unwrap();
489 }
490 }
491 }
492 }
493
494 fn format_select_items(&self, result: &mut String, items: &[SelectItem], indent_level: usize) {
495 if items.is_empty() {
496 write!(result, " *").unwrap();
497 return;
498 }
499
500 let _non_star_count = items
502 .iter()
503 .filter(|i| !matches!(i, SelectItem::Star))
504 .count();
505
506 let has_complex_items = items.iter().any(|item| match item {
508 SelectItem::Expression { expr, .. } => self.is_complex_expression(expr),
509 _ => false,
510 });
511
512 let single_line_length: usize = items
514 .iter()
515 .map(|item| {
516 match item {
517 SelectItem::Star => 1,
518 SelectItem::Column(col) => col.name.len(),
519 SelectItem::Expression { expr, alias } => {
520 self.format_expression(expr).len() + 4 + alias.len() }
522 }
523 })
524 .sum::<usize>()
525 + (items.len() - 1) * 2; let use_single_line = match items.len() {
531 1 => !has_complex_items, 2..=3 => !has_complex_items && single_line_length < 40, _ => false, };
535
536 if !use_single_line {
537 writeln!(result).unwrap();
539 let indent = self.indent(indent_level + 1);
540 for (i, item) in items.iter().enumerate() {
541 write!(result, "{}", indent).unwrap();
542 self.format_select_item(result, item);
543 if i < items.len() - 1 {
544 writeln!(result, ",").unwrap();
545 }
546 }
547 } else {
548 write!(result, " ").unwrap();
550 for (i, item) in items.iter().enumerate() {
551 if i > 0 {
552 write!(result, ", ").unwrap();
553 }
554 self.format_select_item(result, item);
555 }
556 }
557 }
558
559 fn is_complex_expression(&self, expr: &SqlExpression) -> bool {
560 match expr {
561 SqlExpression::CaseExpression { .. } => true,
562 SqlExpression::FunctionCall { .. } => true,
563 SqlExpression::WindowFunction { .. } => true,
564 SqlExpression::ScalarSubquery { .. } => true,
565 SqlExpression::InSubquery { .. } => true,
566 SqlExpression::NotInSubquery { .. } => true,
567 SqlExpression::BinaryOp { left, right, .. } => {
568 self.is_complex_expression(left) || self.is_complex_expression(right)
569 }
570 _ => false,
571 }
572 }
573
574 fn format_select_item(&self, result: &mut String, item: &SelectItem) {
575 match item {
576 SelectItem::Star => write!(result, "*").unwrap(),
577 SelectItem::Column(col) => write!(result, "{}", col.to_sql()).unwrap(),
578 SelectItem::Expression { expr, alias } => {
579 write!(
580 result,
581 "{} {} {}",
582 self.format_expression(expr),
583 self.keyword("AS"),
584 alias
585 )
586 .unwrap();
587 }
588 }
589 }
590
591 fn format_expression(&self, expr: &SqlExpression) -> String {
592 match expr {
593 SqlExpression::Column(column_ref) => column_ref.to_sql(),
594 SqlExpression::StringLiteral(s) => format!("'{}'", s),
595 SqlExpression::NumberLiteral(n) => n.clone(),
596 SqlExpression::BooleanLiteral(b) => b.to_string().to_uppercase(),
597 SqlExpression::Null => self.keyword("NULL"),
598 SqlExpression::BinaryOp { left, op, right } => {
599 if op == "IS NULL" || op == "IS NOT NULL" {
601 format!("{} {}", self.format_expression(left), op)
602 } else {
603 format!(
604 "{} {} {}",
605 self.format_expression(left),
606 op,
607 self.format_expression(right)
608 )
609 }
610 }
611 SqlExpression::FunctionCall {
612 name,
613 args,
614 distinct,
615 } => {
616 let mut result = name.clone();
617 result.push('(');
618 if *distinct {
619 result.push_str(&self.keyword("DISTINCT"));
620 result.push(' ');
621 }
622 for (i, arg) in args.iter().enumerate() {
623 if i > 0 {
624 result.push_str(", ");
625 }
626 result.push_str(&self.format_expression(arg));
627 }
628 result.push(')');
629 result
630 }
631 SqlExpression::CaseExpression {
632 when_branches,
633 else_branch,
634 } => {
635 let mut result = String::new();
637 result.push_str(&self.keyword("CASE"));
638 result.push('\n');
639
640 for branch in when_branches {
642 result.push_str(" "); result.push_str(&format!(
644 "{} {} {} {}",
645 self.keyword("WHEN"),
646 self.format_expression(&branch.condition),
647 self.keyword("THEN"),
648 self.format_expression(&branch.result)
649 ));
650 result.push('\n');
651 }
652
653 if let Some(else_expr) = else_branch {
655 result.push_str(" "); result.push_str(&format!(
657 "{} {}",
658 self.keyword("ELSE"),
659 self.format_expression(else_expr)
660 ));
661 result.push('\n');
662 }
663
664 result.push_str(" "); result.push_str(&self.keyword("END"));
666 result
667 }
668 SqlExpression::SimpleCaseExpression {
669 expr,
670 when_branches,
671 else_branch,
672 } => {
673 let mut result = String::new();
675 result.push_str(&format!(
676 "{} {}",
677 self.keyword("CASE"),
678 self.format_expression(expr)
679 ));
680 result.push('\n');
681
682 for branch in when_branches {
684 result.push_str(" "); result.push_str(&format!(
686 "{} {} {} {}",
687 self.keyword("WHEN"),
688 self.format_expression(&branch.value),
689 self.keyword("THEN"),
690 self.format_expression(&branch.result)
691 ));
692 result.push('\n');
693 }
694
695 if let Some(else_expr) = else_branch {
697 result.push_str(" "); result.push_str(&format!(
699 "{} {}",
700 self.keyword("ELSE"),
701 self.format_expression(else_expr)
702 ));
703 result.push('\n');
704 }
705
706 result.push_str(" "); result.push_str(&self.keyword("END"));
708 result
709 }
710 SqlExpression::Between { expr, lower, upper } => {
711 format!(
712 "{} {} {} {} {}",
713 self.format_expression(expr),
714 self.keyword("BETWEEN"),
715 self.format_expression(lower),
716 self.keyword("AND"),
717 self.format_expression(upper)
718 )
719 }
720 SqlExpression::InList { expr, values } => {
721 let mut result =
722 format!("{} {} (", self.format_expression(expr), self.keyword("IN"));
723 for (i, val) in values.iter().enumerate() {
724 if i > 0 {
725 result.push_str(", ");
726 }
727 result.push_str(&self.format_expression(val));
728 }
729 result.push(')');
730 result
731 }
732 SqlExpression::NotInList { expr, values } => {
733 let mut result = format!(
734 "{} {} {} (",
735 self.format_expression(expr),
736 self.keyword("NOT"),
737 self.keyword("IN")
738 );
739 for (i, val) in values.iter().enumerate() {
740 if i > 0 {
741 result.push_str(", ");
742 }
743 result.push_str(&self.format_expression(val));
744 }
745 result.push(')');
746 result
747 }
748 SqlExpression::Not { expr } => {
749 format!("{} {}", self.keyword("NOT"), self.format_expression(expr))
750 }
751 SqlExpression::ScalarSubquery { query } => {
752 let subquery_str = self.format_select(query, 0);
754 if subquery_str.contains('\n') || subquery_str.len() > 60 {
755 format!("(\n{}\n)", self.format_select(query, 1))
757 } else {
758 format!("({})", subquery_str)
760 }
761 }
762 SqlExpression::InSubquery { expr, subquery } => {
763 let subquery_str = self.format_select(subquery, 0);
764 if subquery_str.contains('\n') || subquery_str.len() > 60 {
765 format!(
767 "{} {} (\n{}\n)",
768 self.format_expression(expr),
769 self.keyword("IN"),
770 self.format_select(subquery, 1)
771 )
772 } else {
773 format!(
775 "{} {} ({})",
776 self.format_expression(expr),
777 self.keyword("IN"),
778 subquery_str
779 )
780 }
781 }
782 SqlExpression::NotInSubquery { expr, subquery } => {
783 let subquery_str = self.format_select(subquery, 0);
784 if subquery_str.contains('\n') || subquery_str.len() > 60 {
785 format!(
787 "{} {} {} (\n{}\n)",
788 self.format_expression(expr),
789 self.keyword("NOT"),
790 self.keyword("IN"),
791 self.format_select(subquery, 1)
792 )
793 } else {
794 format!(
796 "{} {} {} ({})",
797 self.format_expression(expr),
798 self.keyword("NOT"),
799 self.keyword("IN"),
800 subquery_str
801 )
802 }
803 }
804 SqlExpression::MethodCall {
805 object,
806 method,
807 args,
808 } => {
809 let mut result = format!("{}.{}", object, method);
810 result.push('(');
811 for (i, arg) in args.iter().enumerate() {
812 if i > 0 {
813 result.push_str(", ");
814 }
815 result.push_str(&self.format_expression(arg));
816 }
817 result.push(')');
818 result
819 }
820 SqlExpression::ChainedMethodCall { base, method, args } => {
821 let mut result = format!("{}.{}", self.format_expression(base), method);
822 result.push('(');
823 for (i, arg) in args.iter().enumerate() {
824 if i > 0 {
825 result.push_str(", ");
826 }
827 result.push_str(&self.format_expression(arg));
828 }
829 result.push(')');
830 result
831 }
832 SqlExpression::WindowFunction {
833 name,
834 args,
835 window_spec,
836 } => {
837 let mut result = format!("{}(", name);
838
839 for (i, arg) in args.iter().enumerate() {
841 if i > 0 {
842 result.push_str(", ");
843 }
844 result.push_str(&self.format_expression(arg));
845 }
846 result.push_str(") ");
847 result.push_str(&self.keyword("OVER"));
848 result.push_str(" (");
849
850 if !window_spec.partition_by.is_empty() {
852 result.push_str(&self.keyword("PARTITION BY"));
853 result.push(' ');
854 for (i, col) in window_spec.partition_by.iter().enumerate() {
855 if i > 0 {
856 result.push_str(", ");
857 }
858 result.push_str(col);
859 }
860 }
861
862 if !window_spec.order_by.is_empty() {
864 if !window_spec.partition_by.is_empty() {
865 result.push(' ');
866 }
867 result.push_str(&self.keyword("ORDER BY"));
868 result.push(' ');
869 for (i, col) in window_spec.order_by.iter().enumerate() {
870 if i > 0 {
871 result.push_str(", ");
872 }
873 result.push_str(&col.column);
874 match col.direction {
875 SortDirection::Asc => {
876 result.push(' ');
877 result.push_str(&self.keyword("ASC"));
878 }
879 SortDirection::Desc => {
880 result.push(' ');
881 result.push_str(&self.keyword("DESC"));
882 }
883 }
884 }
885 }
886
887 if let Some(frame) = &window_spec.frame {
889 if !window_spec.partition_by.is_empty() || !window_spec.order_by.is_empty() {
891 result.push(' ');
892 }
893
894 match frame.unit {
896 FrameUnit::Rows => result.push_str(&self.keyword("ROWS")),
897 FrameUnit::Range => result.push_str(&self.keyword("RANGE")),
898 }
899
900 result.push(' ');
901
902 if let Some(end) = &frame.end {
904 result.push_str(&self.keyword("BETWEEN"));
906 result.push(' ');
907 result.push_str(&self.format_frame_bound(&frame.start));
908 result.push(' ');
909 result.push_str(&self.keyword("AND"));
910 result.push(' ');
911 result.push_str(&self.format_frame_bound(end));
912 } else {
913 result.push_str(&self.format_frame_bound(&frame.start));
915 }
916 }
917
918 result.push(')');
919 result
920 }
921 SqlExpression::DateTimeConstructor {
922 year,
923 month,
924 day,
925 hour,
926 minute,
927 second,
928 } => {
929 if let (Some(h), Some(m), Some(s)) = (hour, minute, second) {
930 format!(
931 "DateTime({}, {}, {}, {}, {}, {})",
932 year, month, day, h, m, s
933 )
934 } else {
935 format!("DateTime({}, {}, {})", year, month, day)
936 }
937 }
938 SqlExpression::DateTimeToday {
939 hour,
940 minute,
941 second,
942 } => {
943 if let (Some(h), Some(m), Some(s)) = (hour, minute, second) {
944 format!("Today({}, {}, {})", h, m, s)
945 } else {
946 "Today()".to_string()
947 }
948 }
949 _ => format!("{:?}", expr), }
951 }
952
953 fn format_where_clause(
954 &self,
955 result: &mut String,
956 where_clause: &WhereClause,
957 indent_level: usize,
958 ) {
959 let needs_multiline = where_clause.conditions.len() > 1;
960
961 if needs_multiline {
962 writeln!(result).unwrap();
963 let indent = self.indent(indent_level + 1);
964 for (i, condition) in where_clause.conditions.iter().enumerate() {
965 if i > 0 {
966 if let Some(ref connector) = where_clause.conditions[i - 1].connector {
967 let connector_str = match connector {
968 LogicalOp::And => self.keyword("AND"),
969 LogicalOp::Or => self.keyword("OR"),
970 };
971 writeln!(result).unwrap();
972 write!(result, "{}{} ", indent, connector_str).unwrap();
973 }
974 } else {
975 write!(result, "{}", indent).unwrap();
976 }
977 write!(result, "{}", self.format_expression(&condition.expr)).unwrap();
978 }
979 } else if let Some(condition) = where_clause.conditions.first() {
980 write!(result, " {}", self.format_expression(&condition.expr)).unwrap();
981 }
982 }
983
984 fn format_frame_bound(&self, bound: &FrameBound) -> String {
985 match bound {
986 FrameBound::UnboundedPreceding => self.keyword("UNBOUNDED PRECEDING"),
987 FrameBound::CurrentRow => self.keyword("CURRENT ROW"),
988 FrameBound::UnboundedFollowing => self.keyword("UNBOUNDED FOLLOWING"),
989 FrameBound::Preceding(n) => format!("{} {}", n, self.keyword("PRECEDING")),
990 FrameBound::Following(n) => format!("{} {}", n, self.keyword("FOLLOWING")),
991 }
992 }
993
994 fn format_join(&self, result: &mut String, join: &JoinClause, indent_level: usize) {
995 let indent = self.indent(indent_level);
996 let join_type = match join.join_type {
997 JoinType::Inner => self.keyword("INNER JOIN"),
998 JoinType::Left => self.keyword("LEFT JOIN"),
999 JoinType::Right => self.keyword("RIGHT JOIN"),
1000 JoinType::Full => self.keyword("FULL JOIN"),
1001 JoinType::Cross => self.keyword("CROSS JOIN"),
1002 };
1003
1004 write!(result, "{}{} ", indent, join_type).unwrap();
1005
1006 match &join.table {
1007 TableSource::Table(name) => write!(result, "{}", name).unwrap(),
1008 TableSource::DerivedTable { query, alias } => {
1009 writeln!(result, "(").unwrap();
1010 let subquery_sql = self.format_select(query, indent_level + 1);
1011 write!(result, "{}", subquery_sql).unwrap();
1012 writeln!(result).unwrap();
1013 write!(result, "{}) {} {}", indent, self.keyword("AS"), alias).unwrap();
1014 }
1015 }
1016
1017 if let Some(ref alias) = join.alias {
1018 write!(result, " {} {}", self.keyword("AS"), alias).unwrap();
1019 }
1020
1021 if !join.condition.conditions.is_empty() {
1022 write!(result, " {}", self.keyword("ON")).unwrap();
1023 for (i, condition) in join.condition.conditions.iter().enumerate() {
1024 if i > 0 {
1025 write!(result, " {}", self.keyword("AND")).unwrap();
1026 }
1027 write!(
1028 result,
1029 " {} {} {}",
1030 condition.left_column,
1031 self.format_join_operator(&condition.operator),
1032 condition.right_column
1033 )
1034 .unwrap();
1035 }
1036 }
1037 }
1038
1039 fn format_join_operator(&self, op: &JoinOperator) -> String {
1040 match op {
1041 JoinOperator::Equal => "=",
1042 JoinOperator::NotEqual => "!=",
1043 JoinOperator::LessThan => "<",
1044 JoinOperator::GreaterThan => ">",
1045 JoinOperator::LessThanOrEqual => "<=",
1046 JoinOperator::GreaterThanOrEqual => ">=",
1047 }
1048 .to_string()
1049 }
1050
1051 fn format_table_function(&self, result: &mut String, func: &TableFunction) {
1052 match func {
1053 TableFunction::Generator { name, args } => {
1054 write!(result, "{}(", self.keyword(&name.to_uppercase())).unwrap();
1055 for (i, arg) in args.iter().enumerate() {
1056 if i > 0 {
1057 write!(result, ", ").unwrap();
1058 }
1059 write!(result, "{}", self.format_expression(arg)).unwrap();
1060 }
1061 write!(result, ")").unwrap();
1062 }
1063 }
1064 }
1065}
1066
1067pub fn format_sql_ast(query: &str) -> Result<String, String> {
1069 use crate::sql::recursive_parser::Parser;
1070
1071 let mut parser = Parser::new(query);
1072 match parser.parse() {
1073 Ok(stmt) => Ok(format_select_statement(&stmt)),
1074 Err(e) => Err(format!("Parse error: {}", e)),
1075 }
1076}
1077
1078pub fn format_sql_ast_with_config(query: &str, config: &FormatConfig) -> Result<String, String> {
1080 use crate::sql::recursive_parser::Parser;
1081
1082 let mut parser = Parser::new(query);
1083 match parser.parse() {
1084 Ok(stmt) => Ok(format_select_with_config(&stmt, &config)),
1085 Err(e) => Err(format!("Parse error: {}", e)),
1086 }
1087}