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
44struct AstFormatter<'a> {
45 config: &'a FormatConfig,
46}
47
48impl<'a> AstFormatter<'a> {
49 fn new(config: &'a FormatConfig) -> Self {
50 Self { config }
51 }
52
53 fn keyword(&self, word: &str) -> String {
54 if self.config.uppercase_keywords {
55 word.to_uppercase()
56 } else {
57 word.to_lowercase()
58 }
59 }
60
61 fn indent(&self, level: usize) -> String {
62 self.config.indent.repeat(level)
63 }
64
65 fn format_select(&self, stmt: &SelectStatement, indent_level: usize) -> String {
66 let mut result = String::new();
67 let indent = self.indent(indent_level);
68
69 if !stmt.ctes.is_empty() {
71 writeln!(&mut result, "{}{}", indent, self.keyword("WITH")).unwrap();
72 for (i, cte) in stmt.ctes.iter().enumerate() {
73 let is_last = i == stmt.ctes.len() - 1;
74 self.format_cte(&mut result, cte, indent_level + 1, is_last);
75 }
76 }
77
78 write!(&mut result, "{}{}", indent, self.keyword("SELECT")).unwrap();
80 if stmt.distinct {
81 write!(&mut result, " {}", self.keyword("DISTINCT")).unwrap();
82 }
83
84 if stmt.select_items.is_empty() && !stmt.columns.is_empty() {
86 self.format_column_list(&mut result, &stmt.columns, indent_level);
88 } else {
89 self.format_select_items(&mut result, &stmt.select_items, indent_level);
90 }
91
92 if let Some(ref table) = stmt.from_table {
94 writeln!(&mut result).unwrap();
95 write!(&mut result, "{}{} {}", indent, self.keyword("FROM"), table).unwrap();
96 } else if let Some(ref subquery) = stmt.from_subquery {
97 writeln!(&mut result).unwrap();
98 write!(&mut result, "{}{} (", indent, self.keyword("FROM")).unwrap();
99 writeln!(&mut result).unwrap();
100 let subquery_sql = self.format_select(subquery, indent_level + 1);
101 write!(&mut result, "{}", subquery_sql).unwrap();
102 write!(&mut result, "\n{}", indent).unwrap();
103 write!(&mut result, ")").unwrap();
104 if let Some(ref alias) = stmt.from_alias {
105 write!(&mut result, " {} {}", self.keyword("AS"), alias).unwrap();
106 }
107 } else if let Some(ref func) = stmt.from_function {
108 writeln!(&mut result).unwrap();
109 write!(&mut result, "{}{} ", indent, self.keyword("FROM")).unwrap();
110 self.format_table_function(&mut result, func);
111 if let Some(ref alias) = stmt.from_alias {
112 write!(&mut result, " {} {}", self.keyword("AS"), alias).unwrap();
113 }
114 }
115
116 for join in &stmt.joins {
118 writeln!(&mut result).unwrap();
119 self.format_join(&mut result, join, indent_level);
120 }
121
122 if let Some(ref where_clause) = stmt.where_clause {
124 writeln!(&mut result).unwrap();
125 write!(&mut result, "{}{}", indent, self.keyword("WHERE")).unwrap();
126 self.format_where_clause(&mut result, where_clause, indent_level);
127 }
128
129 if let Some(ref group_by) = stmt.group_by {
131 writeln!(&mut result).unwrap();
132 write!(&mut result, "{}{} ", indent, self.keyword("GROUP BY")).unwrap();
133 for (i, expr) in group_by.iter().enumerate() {
134 if i > 0 {
135 write!(&mut result, ", ").unwrap();
136 }
137 write!(&mut result, "{}", self.format_expression(expr)).unwrap();
138 }
139 }
140
141 if let Some(ref having) = stmt.having {
143 writeln!(&mut result).unwrap();
144 write!(
145 &mut result,
146 "{}{} {}",
147 indent,
148 self.keyword("HAVING"),
149 self.format_expression(having)
150 )
151 .unwrap();
152 }
153
154 if let Some(ref order_by) = stmt.order_by {
156 writeln!(&mut result).unwrap();
157 write!(&mut result, "{}{} ", indent, self.keyword("ORDER BY")).unwrap();
158 for (i, col) in order_by.iter().enumerate() {
159 if i > 0 {
160 write!(&mut result, ", ").unwrap();
161 }
162 write!(&mut result, "{}", col.column).unwrap();
163 match col.direction {
164 SortDirection::Asc => write!(&mut result, " {}", self.keyword("ASC")).unwrap(),
165 SortDirection::Desc => {
166 write!(&mut result, " {}", self.keyword("DESC")).unwrap()
167 }
168 }
169 }
170 }
171
172 if let Some(limit) = stmt.limit {
174 writeln!(&mut result).unwrap();
175 write!(&mut result, "{}{} {}", indent, self.keyword("LIMIT"), limit).unwrap();
176 }
177
178 if let Some(offset) = stmt.offset {
180 writeln!(&mut result).unwrap();
181 write!(
182 &mut result,
183 "{}{} {}",
184 indent,
185 self.keyword("OFFSET"),
186 offset
187 )
188 .unwrap();
189 }
190
191 result
192 }
193
194 fn format_cte(&self, result: &mut String, cte: &CTE, indent_level: usize, is_last: bool) {
195 let indent = self.indent(indent_level);
196
197 let is_web = matches!(&cte.cte_type, crate::sql::parser::ast::CTEType::Web(_));
199 if is_web {
200 write!(result, "{}{} {}", indent, self.keyword("WEB"), cte.name).unwrap();
201 } else {
202 write!(result, "{}{}", indent, cte.name).unwrap();
203 }
204
205 if let Some(ref columns) = cte.column_list {
206 write!(result, "(").unwrap();
207 for (i, col) in columns.iter().enumerate() {
208 if i > 0 {
209 write!(result, ", ").unwrap();
210 }
211 write!(result, "{}", col).unwrap();
212 }
213 write!(result, ")").unwrap();
214 }
215
216 writeln!(result, " {} (", self.keyword("AS")).unwrap();
217 let cte_sql = match &cte.cte_type {
218 crate::sql::parser::ast::CTEType::Standard(query) => {
219 self.format_select(query, indent_level + 1)
220 }
221 crate::sql::parser::ast::CTEType::Web(web_spec) => {
222 let mut web_str = format!(
224 "{}{} '{}'",
225 " ".repeat(indent_level + 1),
226 self.keyword("URL"),
227 web_spec.url
228 );
229
230 if let Some(method) = &web_spec.method {
232 web_str.push_str(&format!(
233 " {} {}",
234 self.keyword("METHOD"),
235 match method {
236 crate::sql::parser::ast::HttpMethod::GET => "GET",
237 crate::sql::parser::ast::HttpMethod::POST => "POST",
238 crate::sql::parser::ast::HttpMethod::PUT => "PUT",
239 crate::sql::parser::ast::HttpMethod::DELETE => "DELETE",
240 crate::sql::parser::ast::HttpMethod::PATCH => "PATCH",
241 }
242 ));
243 }
244
245 if let Some(body) = &web_spec.body {
247 web_str.push_str(&format!(" {} '{}'", self.keyword("BODY"), body));
248 }
249
250 if let Some(format) = &web_spec.format {
252 web_str.push_str(&format!(
253 " {} {}",
254 self.keyword("FORMAT"),
255 match format {
256 crate::sql::parser::ast::DataFormat::CSV => "CSV",
257 crate::sql::parser::ast::DataFormat::JSON => "JSON",
258 crate::sql::parser::ast::DataFormat::Auto => "AUTO",
259 }
260 ));
261 }
262
263 if let Some(json_path) = &web_spec.json_path {
265 web_str.push_str(&format!(" {} '{}'", self.keyword("JSON_PATH"), json_path));
266 }
267
268 if let Some(cache) = web_spec.cache_seconds {
270 web_str.push_str(&format!(" {} {}", self.keyword("CACHE"), cache));
271 }
272
273 for (field_name, file_path) in &web_spec.form_files {
275 web_str.push_str(&format!(
276 "\n{}{} '{}' '{}'",
277 " ".repeat(indent_level + 1),
278 self.keyword("FORM_FILE"),
279 field_name,
280 file_path
281 ));
282 }
283
284 for (field_name, value) in &web_spec.form_fields {
286 let trimmed_value = value.trim();
288 if (trimmed_value.starts_with('{') && trimmed_value.ends_with('}'))
289 || (trimmed_value.starts_with('[') && trimmed_value.ends_with(']'))
290 {
291 match serde_json::from_str::<serde_json::Value>(trimmed_value) {
293 Ok(json_val) => {
294 match serde_json::to_string_pretty(&json_val) {
296 Ok(pretty_json) => {
297 let base_indent = " ".repeat(indent_level + 1);
299 let json_lines: Vec<String> = pretty_json
300 .lines()
301 .enumerate()
302 .map(|(i, line)| {
303 if i == 0 {
304 line.to_string()
305 } else {
306 format!("{}{}", base_indent, line)
307 }
308 })
309 .collect();
310 let formatted_json = json_lines.join("\n");
311
312 web_str.push_str(&format!(
313 "\n{}{} '{}' '{}'\n",
314 base_indent,
315 self.keyword("FORM_FIELD"),
316 field_name,
317 formatted_json
318 ));
319 }
320 Err(_) => {
321 web_str.push_str(&format!(
323 "\n{}{} '{}' '{}'",
324 " ".repeat(indent_level + 1),
325 self.keyword("FORM_FIELD"),
326 field_name,
327 value
328 ));
329 }
330 }
331 }
332 Err(_) => {
333 web_str.push_str(&format!(
335 "\n{}{} '{}' '{}'",
336 " ".repeat(indent_level + 1),
337 self.keyword("FORM_FIELD"),
338 field_name,
339 value
340 ));
341 }
342 }
343 } else {
344 web_str.push_str(&format!(
346 "\n{}{} '{}' '{}'",
347 " ".repeat(indent_level + 1),
348 self.keyword("FORM_FIELD"),
349 field_name,
350 value
351 ));
352 }
353 }
354
355 if !web_spec.headers.is_empty() {
357 web_str.push_str(&format!(" {} (", self.keyword("HEADERS")));
358 for (i, (key, value)) in web_spec.headers.iter().enumerate() {
359 if i > 0 {
360 web_str.push_str(", ");
361 }
362 web_str.push_str(&format!("'{}': '{}'", key, value));
363 }
364 web_str.push(')');
365 }
366
367 web_str
368 }
369 };
370 write!(result, "{}", cte_sql).unwrap();
371 writeln!(result).unwrap();
372 write!(result, "{}", indent).unwrap();
373 if is_last {
374 writeln!(result, ")").unwrap();
375 } else {
376 writeln!(result, "),").unwrap();
377 }
378 }
379
380 fn format_column_list(&self, result: &mut String, columns: &[String], indent_level: usize) {
381 if columns.len() <= self.config.items_per_line {
382 write!(result, " ").unwrap();
384 for (i, col) in columns.iter().enumerate() {
385 if i > 0 {
386 write!(result, ", ").unwrap();
387 }
388 write!(result, "{}", col).unwrap();
389 }
390 } else {
391 writeln!(result).unwrap();
393 let indent = self.indent(indent_level + 1);
394 for (i, col) in columns.iter().enumerate() {
395 write!(result, "{}{}", indent, col).unwrap();
396 if i < columns.len() - 1 {
397 writeln!(result, ",").unwrap();
398 }
399 }
400 }
401 }
402
403 fn format_select_items(&self, result: &mut String, items: &[SelectItem], indent_level: usize) {
404 if items.is_empty() {
405 write!(result, " *").unwrap();
406 return;
407 }
408
409 let non_star_count = items
411 .iter()
412 .filter(|i| !matches!(i, SelectItem::Star))
413 .count();
414
415 let has_complex_items = items.iter().any(|item| match item {
417 SelectItem::Expression { expr, .. } => self.is_complex_expression(expr),
418 _ => false,
419 });
420
421 let single_line_length: usize = items
423 .iter()
424 .map(|item| {
425 match item {
426 SelectItem::Star => 1,
427 SelectItem::Column(col) => col.name.len(),
428 SelectItem::Expression { expr, alias } => {
429 self.format_expression(expr).len() + 4 + alias.len() }
431 }
432 })
433 .sum::<usize>()
434 + (items.len() - 1) * 2; let use_single_line = match items.len() {
440 1 => !has_complex_items, 2..=3 => !has_complex_items && single_line_length < 40, _ => false, };
444
445 if !use_single_line {
446 writeln!(result).unwrap();
448 let indent = self.indent(indent_level + 1);
449 for (i, item) in items.iter().enumerate() {
450 write!(result, "{}", indent).unwrap();
451 self.format_select_item(result, item);
452 if i < items.len() - 1 {
453 writeln!(result, ",").unwrap();
454 }
455 }
456 } else {
457 write!(result, " ").unwrap();
459 for (i, item) in items.iter().enumerate() {
460 if i > 0 {
461 write!(result, ", ").unwrap();
462 }
463 self.format_select_item(result, item);
464 }
465 }
466 }
467
468 fn is_complex_expression(&self, expr: &SqlExpression) -> bool {
469 match expr {
470 SqlExpression::CaseExpression { .. } => true,
471 SqlExpression::FunctionCall { .. } => true,
472 SqlExpression::WindowFunction { .. } => true,
473 SqlExpression::ScalarSubquery { .. } => true,
474 SqlExpression::InSubquery { .. } => true,
475 SqlExpression::NotInSubquery { .. } => true,
476 SqlExpression::BinaryOp { left, right, .. } => {
477 self.is_complex_expression(left) || self.is_complex_expression(right)
478 }
479 _ => false,
480 }
481 }
482
483 fn format_select_item(&self, result: &mut String, item: &SelectItem) {
484 match item {
485 SelectItem::Star => write!(result, "*").unwrap(),
486 SelectItem::Column(col) => write!(result, "{}", col.to_sql()).unwrap(),
487 SelectItem::Expression { expr, alias } => {
488 write!(
489 result,
490 "{} {} {}",
491 self.format_expression(expr),
492 self.keyword("AS"),
493 alias
494 )
495 .unwrap();
496 }
497 }
498 }
499
500 fn format_expression(&self, expr: &SqlExpression) -> String {
501 match expr {
502 SqlExpression::Column(column_ref) => column_ref.to_sql(),
503 SqlExpression::StringLiteral(s) => format!("'{}'", s),
504 SqlExpression::NumberLiteral(n) => n.clone(),
505 SqlExpression::BooleanLiteral(b) => b.to_string().to_uppercase(),
506 SqlExpression::Null => self.keyword("NULL"),
507 SqlExpression::BinaryOp { left, op, right } => {
508 if op == "IS NULL" || op == "IS NOT NULL" {
510 format!("{} {}", self.format_expression(left), op)
511 } else {
512 format!(
513 "{} {} {}",
514 self.format_expression(left),
515 op,
516 self.format_expression(right)
517 )
518 }
519 }
520 SqlExpression::FunctionCall {
521 name,
522 args,
523 distinct,
524 } => {
525 let mut result = name.clone();
526 result.push('(');
527 if *distinct {
528 result.push_str(&self.keyword("DISTINCT"));
529 result.push(' ');
530 }
531 for (i, arg) in args.iter().enumerate() {
532 if i > 0 {
533 result.push_str(", ");
534 }
535 result.push_str(&self.format_expression(arg));
536 }
537 result.push(')');
538 result
539 }
540 SqlExpression::CaseExpression {
541 when_branches,
542 else_branch,
543 } => {
544 let mut result = String::new();
546 result.push_str(&self.keyword("CASE"));
547 result.push('\n');
548
549 for branch in when_branches {
551 result.push_str(" "); result.push_str(&format!(
553 "{} {} {} {}",
554 self.keyword("WHEN"),
555 self.format_expression(&branch.condition),
556 self.keyword("THEN"),
557 self.format_expression(&branch.result)
558 ));
559 result.push('\n');
560 }
561
562 if let Some(else_expr) = else_branch {
564 result.push_str(" "); result.push_str(&format!(
566 "{} {}",
567 self.keyword("ELSE"),
568 self.format_expression(else_expr)
569 ));
570 result.push('\n');
571 }
572
573 result.push_str(" "); result.push_str(&self.keyword("END"));
575 result
576 }
577 SqlExpression::Between { expr, lower, upper } => {
578 format!(
579 "{} {} {} {} {}",
580 self.format_expression(expr),
581 self.keyword("BETWEEN"),
582 self.format_expression(lower),
583 self.keyword("AND"),
584 self.format_expression(upper)
585 )
586 }
587 SqlExpression::InList { expr, values } => {
588 let mut result =
589 format!("{} {} (", self.format_expression(expr), self.keyword("IN"));
590 for (i, val) in values.iter().enumerate() {
591 if i > 0 {
592 result.push_str(", ");
593 }
594 result.push_str(&self.format_expression(val));
595 }
596 result.push(')');
597 result
598 }
599 SqlExpression::NotInList { expr, values } => {
600 let mut result = format!(
601 "{} {} {} (",
602 self.format_expression(expr),
603 self.keyword("NOT"),
604 self.keyword("IN")
605 );
606 for (i, val) in values.iter().enumerate() {
607 if i > 0 {
608 result.push_str(", ");
609 }
610 result.push_str(&self.format_expression(val));
611 }
612 result.push(')');
613 result
614 }
615 SqlExpression::Not { expr } => {
616 format!("{} {}", self.keyword("NOT"), self.format_expression(expr))
617 }
618 SqlExpression::ScalarSubquery { query } => {
619 let subquery_str = self.format_select(query, 0);
621 if subquery_str.contains('\n') || subquery_str.len() > 60 {
622 format!("(\n{}\n)", self.format_select(query, 1))
624 } else {
625 format!("({})", subquery_str)
627 }
628 }
629 SqlExpression::InSubquery { expr, subquery } => {
630 let subquery_str = self.format_select(subquery, 0);
631 if subquery_str.contains('\n') || subquery_str.len() > 60 {
632 format!(
634 "{} {} (\n{}\n)",
635 self.format_expression(expr),
636 self.keyword("IN"),
637 self.format_select(subquery, 1)
638 )
639 } else {
640 format!(
642 "{} {} ({})",
643 self.format_expression(expr),
644 self.keyword("IN"),
645 subquery_str
646 )
647 }
648 }
649 SqlExpression::NotInSubquery { expr, subquery } => {
650 let subquery_str = self.format_select(subquery, 0);
651 if subquery_str.contains('\n') || subquery_str.len() > 60 {
652 format!(
654 "{} {} {} (\n{}\n)",
655 self.format_expression(expr),
656 self.keyword("NOT"),
657 self.keyword("IN"),
658 self.format_select(subquery, 1)
659 )
660 } else {
661 format!(
663 "{} {} {} ({})",
664 self.format_expression(expr),
665 self.keyword("NOT"),
666 self.keyword("IN"),
667 subquery_str
668 )
669 }
670 }
671 SqlExpression::MethodCall {
672 object,
673 method,
674 args,
675 } => {
676 let mut result = format!("{}.{}", object, method);
677 result.push('(');
678 for (i, arg) in args.iter().enumerate() {
679 if i > 0 {
680 result.push_str(", ");
681 }
682 result.push_str(&self.format_expression(arg));
683 }
684 result.push(')');
685 result
686 }
687 SqlExpression::ChainedMethodCall { base, method, args } => {
688 let mut result = format!("{}.{}", self.format_expression(base), method);
689 result.push('(');
690 for (i, arg) in args.iter().enumerate() {
691 if i > 0 {
692 result.push_str(", ");
693 }
694 result.push_str(&self.format_expression(arg));
695 }
696 result.push(')');
697 result
698 }
699 SqlExpression::WindowFunction {
700 name,
701 args,
702 window_spec,
703 } => {
704 let mut result = format!("{}(", name);
705
706 for (i, arg) in args.iter().enumerate() {
708 if i > 0 {
709 result.push_str(", ");
710 }
711 result.push_str(&self.format_expression(arg));
712 }
713 result.push_str(") ");
714 result.push_str(&self.keyword("OVER"));
715 result.push_str(" (");
716
717 if !window_spec.partition_by.is_empty() {
719 result.push_str(&self.keyword("PARTITION BY"));
720 result.push(' ');
721 for (i, col) in window_spec.partition_by.iter().enumerate() {
722 if i > 0 {
723 result.push_str(", ");
724 }
725 result.push_str(col);
726 }
727 }
728
729 if !window_spec.order_by.is_empty() {
731 if !window_spec.partition_by.is_empty() {
732 result.push(' ');
733 }
734 result.push_str(&self.keyword("ORDER BY"));
735 result.push(' ');
736 for (i, col) in window_spec.order_by.iter().enumerate() {
737 if i > 0 {
738 result.push_str(", ");
739 }
740 result.push_str(&col.column);
741 match col.direction {
742 SortDirection::Asc => {
743 result.push(' ');
744 result.push_str(&self.keyword("ASC"));
745 }
746 SortDirection::Desc => {
747 result.push(' ');
748 result.push_str(&self.keyword("DESC"));
749 }
750 }
751 }
752 }
753
754 result.push(')');
755 result
756 }
757 _ => format!("{:?}", expr), }
759 }
760
761 fn format_where_clause(
762 &self,
763 result: &mut String,
764 where_clause: &WhereClause,
765 indent_level: usize,
766 ) {
767 let needs_multiline = where_clause.conditions.len() > 1;
768
769 if needs_multiline {
770 writeln!(result).unwrap();
771 let indent = self.indent(indent_level + 1);
772 for (i, condition) in where_clause.conditions.iter().enumerate() {
773 if i > 0 {
774 if let Some(ref connector) = where_clause.conditions[i - 1].connector {
775 let connector_str = match connector {
776 LogicalOp::And => self.keyword("AND"),
777 LogicalOp::Or => self.keyword("OR"),
778 };
779 writeln!(result).unwrap();
780 write!(result, "{}{} ", indent, connector_str).unwrap();
781 }
782 } else {
783 write!(result, "{}", indent).unwrap();
784 }
785 write!(result, "{}", self.format_expression(&condition.expr)).unwrap();
786 }
787 } else if let Some(condition) = where_clause.conditions.first() {
788 write!(result, " {}", self.format_expression(&condition.expr)).unwrap();
789 }
790 }
791
792 fn format_join(&self, result: &mut String, join: &JoinClause, indent_level: usize) {
793 let indent = self.indent(indent_level);
794 let join_type = match join.join_type {
795 JoinType::Inner => self.keyword("INNER JOIN"),
796 JoinType::Left => self.keyword("LEFT JOIN"),
797 JoinType::Right => self.keyword("RIGHT JOIN"),
798 JoinType::Full => self.keyword("FULL JOIN"),
799 JoinType::Cross => self.keyword("CROSS JOIN"),
800 };
801
802 write!(result, "{}{} ", indent, join_type).unwrap();
803
804 match &join.table {
805 TableSource::Table(name) => write!(result, "{}", name).unwrap(),
806 TableSource::DerivedTable { query, alias } => {
807 writeln!(result, "(").unwrap();
808 let subquery_sql = self.format_select(query, indent_level + 1);
809 write!(result, "{}", subquery_sql).unwrap();
810 writeln!(result).unwrap();
811 write!(result, "{}) {} {}", indent, self.keyword("AS"), alias).unwrap();
812 }
813 }
814
815 if let Some(ref alias) = join.alias {
816 write!(result, " {} {}", self.keyword("AS"), alias).unwrap();
817 }
818
819 if !join.condition.conditions.is_empty() {
820 write!(result, " {}", self.keyword("ON")).unwrap();
821 for (i, condition) in join.condition.conditions.iter().enumerate() {
822 if i > 0 {
823 write!(result, " {}", self.keyword("AND")).unwrap();
824 }
825 write!(
826 result,
827 " {} {} {}",
828 condition.left_column,
829 self.format_join_operator(&condition.operator),
830 condition.right_column
831 )
832 .unwrap();
833 }
834 }
835 }
836
837 fn format_join_operator(&self, op: &JoinOperator) -> String {
838 match op {
839 JoinOperator::Equal => "=",
840 JoinOperator::NotEqual => "!=",
841 JoinOperator::LessThan => "<",
842 JoinOperator::GreaterThan => ">",
843 JoinOperator::LessThanOrEqual => "<=",
844 JoinOperator::GreaterThanOrEqual => ">=",
845 }
846 .to_string()
847 }
848
849 fn format_table_function(&self, result: &mut String, func: &TableFunction) {
850 match func {
851 TableFunction::Generator { name, args } => {
852 write!(result, "{}(", self.keyword(&name.to_uppercase())).unwrap();
853 for (i, arg) in args.iter().enumerate() {
854 if i > 0 {
855 write!(result, ", ").unwrap();
856 }
857 write!(result, "{}", self.format_expression(arg)).unwrap();
858 }
859 write!(result, ")").unwrap();
860 }
861 }
862 }
863}
864
865pub fn format_sql_ast(query: &str) -> Result<String, String> {
867 use crate::sql::recursive_parser::Parser;
868
869 let mut parser = Parser::new(query);
870 match parser.parse() {
871 Ok(stmt) => Ok(format_select_statement(&stmt)),
872 Err(e) => Err(format!("Parse error: {}", e)),
873 }
874}
875
876pub fn format_sql_ast_with_config(query: &str, config: &FormatConfig) -> Result<String, String> {
878 use crate::sql::recursive_parser::Parser;
879
880 let mut parser = Parser::new(query);
881 match parser.parse() {
882 Ok(stmt) => Ok(format_select_with_config(&stmt, &config)),
883 Err(e) => Err(format!("Parse error: {}", e)),
884 }
885}