1use crate::ast::*;
2use crate::dialects::Dialect;
3
4pub struct Generator {
10 output: String,
11 pretty: bool,
13 indent: usize,
14 dialect: Option<Dialect>,
16}
17
18impl Generator {
19 #[must_use]
20 pub fn new() -> Self {
21 Self {
22 output: String::new(),
23 pretty: false,
24 indent: 0,
25 dialect: None,
26 }
27 }
28
29 #[must_use]
31 pub fn pretty() -> Self {
32 Self {
33 output: String::new(),
34 pretty: true,
35 indent: 0,
36 dialect: None,
37 }
38 }
39
40 #[must_use]
42 pub fn with_dialect(dialect: Dialect) -> Self {
43 Self {
44 output: String::new(),
45 pretty: false,
46 indent: 0,
47 dialect: Some(dialect),
48 }
49 }
50
51 #[must_use]
53 pub fn generate(&mut self, statement: &Statement) -> String {
54 self.output.clear();
55 self.gen_statement(statement);
56 self.output.clone()
57 }
58
59 #[must_use]
61 pub fn expr_to_sql(expr: &Expr) -> String {
62 let mut g = Self::new();
63 g.gen_expr(expr);
64 g.output
65 }
66
67 fn write(&mut self, s: &str) {
68 self.output.push_str(s);
69 }
70
71 fn newline(&mut self) {
73 if self.pretty {
74 self.output.push('\n');
75 for _ in 0..self.indent {
76 self.output.push_str(" ");
77 }
78 }
79 }
80
81 fn sep(&mut self) {
83 if self.pretty {
84 self.newline();
85 } else {
86 self.output.push(' ');
87 }
88 }
89
90 fn indent_up(&mut self) {
91 self.indent += 1;
92 }
93
94 fn indent_down(&mut self) {
95 self.indent = self.indent.saturating_sub(1);
96 }
97
98 fn write_keyword(&mut self, s: &str) {
99 self.write(s);
100 }
101
102 fn write_alias(&mut self, alias: &str, style: QuoteStyle) {
107 let effective = if !style.is_quoted()
108 && matches!(self.dialect, Some(d) if crate::dialects::is_tsql_family(d))
109 && crate::dialects::is_tsql_reserved(alias)
110 {
111 QuoteStyle::Bracket
112 } else {
113 style
114 };
115 self.write_quoted(alias, effective);
116 }
117
118 fn write_quoted(&mut self, name: &str, style: QuoteStyle) {
122 let effective_style = if style.is_quoted() {
123 if let Some(dialect) = self.dialect {
124 QuoteStyle::for_dialect(dialect)
125 } else {
126 style
127 }
128 } else {
129 style
130 };
131 match effective_style {
132 QuoteStyle::None => self.write(name),
133 QuoteStyle::DoubleQuote => {
134 self.write("\"");
135 self.write(&name.replace('"', "\"\""));
136 self.write("\"");
137 }
138 QuoteStyle::Backtick => {
139 self.write("`");
140 self.write(&name.replace('`', "``"));
141 self.write("`");
142 }
143 QuoteStyle::Bracket => {
144 self.write("[");
145 self.write(&name.replace(']', "]]"));
146 self.write("]");
147 }
148 }
149 }
150
151 fn gen_comments(&mut self, comments: &[String]) {
159 for comment in comments {
160 let normalized = self.normalize_comment(comment);
161 self.write(&normalized);
162 self.newline_or_space();
163 }
164 }
165
166 fn normalize_comment(&self, comment: &str) -> String {
169 if comment.starts_with('#') {
170 let is_mysql_target = matches!(
171 self.dialect,
172 Some(Dialect::Mysql | Dialect::Doris | Dialect::SingleStore | Dialect::StarRocks)
173 );
174 if !is_mysql_target {
175 return format!("--{}", &comment[1..]);
176 }
177 }
178 comment.to_string()
179 }
180
181 fn newline_or_space(&mut self) {
183 if self.pretty {
184 self.output.push('\n');
185 for _ in 0..self.indent {
186 self.output.push_str(" ");
187 }
188 } else {
189 self.output.push('\n');
190 }
191 }
192
193 fn gen_statement(&mut self, statement: &Statement) {
194 match statement {
196 Statement::Select(s) => {
197 self.gen_comments(&s.comments);
198 self.gen_select(s);
199 }
200 Statement::Insert(s) => {
201 self.gen_comments(&s.comments);
202 self.gen_insert(s);
203 }
204 Statement::Update(s) => {
205 self.gen_comments(&s.comments);
206 self.gen_update(s);
207 }
208 Statement::Delete(s) => {
209 self.gen_comments(&s.comments);
210 self.gen_delete(s);
211 }
212 Statement::CreateTable(s) => {
213 self.gen_comments(&s.comments);
214 self.gen_create_table(s);
215 }
216 Statement::DropTable(s) => {
217 self.gen_comments(&s.comments);
218 self.gen_drop_table(s);
219 }
220 Statement::SetOperation(s) => {
221 self.gen_comments(&s.comments);
222 self.gen_set_operation(s);
223 }
224 Statement::AlterTable(s) => {
225 self.gen_comments(&s.comments);
226 self.gen_alter_table(s);
227 }
228 Statement::CreateView(s) => {
229 self.gen_comments(&s.comments);
230 self.gen_create_view(s);
231 }
232 Statement::DropView(s) => {
233 self.gen_comments(&s.comments);
234 self.gen_drop_view(s);
235 }
236 Statement::Truncate(s) => {
237 self.gen_comments(&s.comments);
238 self.gen_truncate(s);
239 }
240 Statement::Transaction(s) => self.gen_transaction(s),
241 Statement::Explain(s) => {
242 self.gen_comments(&s.comments);
243 self.gen_explain(s);
244 }
245 Statement::Use(s) => {
246 self.gen_comments(&s.comments);
247 self.gen_use(s);
248 }
249 Statement::Merge(s) => {
250 self.gen_comments(&s.comments);
251 self.gen_merge(s);
252 }
253 Statement::Expression(e) => self.gen_expr(e),
254 Statement::Command(s) => {
255 self.gen_comments(&s.comments);
256 self.gen_command(s);
257 }
258 }
259 }
260
261 fn gen_command(&mut self, c: &crate::ast::CommandStatement) {
262 self.write(&c.kind);
263 if !c.body.is_empty() {
264 self.write(" ");
265 self.write(&c.body);
266 }
267 }
268
269 fn gen_select(&mut self, sel: &SelectStatement) {
272 if !sel.ctes.is_empty() {
274 self.gen_ctes(&sel.ctes);
275 self.sep();
276 }
277
278 self.write_keyword("SELECT");
279 if sel.distinct {
280 self.write(" ");
281 self.write_keyword("DISTINCT");
282 }
283 if let Some(top) = &sel.top {
284 self.write(" ");
285 self.write_keyword("TOP ");
286 self.gen_expr(top);
287 }
288
289 if self.pretty {
291 self.indent_up();
292 for (i, item) in sel.columns.iter().enumerate() {
293 self.newline();
294 self.gen_select_item(item);
295 if i < sel.columns.len() - 1 {
296 self.write(",");
297 }
298 }
299 self.indent_down();
300 } else {
301 self.write(" ");
302 for (i, item) in sel.columns.iter().enumerate() {
303 if i > 0 {
304 self.write(", ");
305 }
306 self.gen_select_item(item);
307 }
308 }
309
310 if let Some(from) = &sel.from {
311 self.sep();
312 self.write_keyword("FROM");
313 if self.pretty {
314 self.indent_up();
315 self.newline();
316 self.gen_table_source(&from.source);
317 self.indent_down();
318 } else {
319 self.write(" ");
320 self.gen_table_source(&from.source);
321 }
322 }
323
324 for join in &sel.joins {
325 self.gen_join(join);
326 }
327
328 if let Some(wh) = &sel.where_clause {
329 self.sep();
330 self.write_keyword("WHERE");
331 if self.pretty {
332 self.indent_up();
333 self.newline();
334 self.gen_condition(wh);
335 self.indent_down();
336 } else {
337 self.write(" ");
338 self.gen_condition(wh);
339 }
340 }
341
342 if !sel.group_by.is_empty() {
343 self.sep();
344 self.write_keyword("GROUP BY");
345 if self.pretty {
346 self.indent_up();
347 self.newline();
348 self.gen_expr_list(&sel.group_by);
349 self.indent_down();
350 } else {
351 self.write(" ");
352 self.gen_expr_list(&sel.group_by);
353 }
354 }
355
356 if let Some(having) = &sel.having {
357 self.sep();
358 self.write_keyword("HAVING");
359 if self.pretty {
360 self.indent_up();
361 self.newline();
362 self.gen_condition(having);
363 self.indent_down();
364 } else {
365 self.write(" ");
366 self.gen_condition(having);
367 }
368 }
369
370 if let Some(qualify) = &sel.qualify {
371 self.sep();
372 self.write_keyword("QUALIFY");
373 if self.pretty {
374 self.indent_up();
375 self.newline();
376 self.gen_condition(qualify);
377 self.indent_down();
378 } else {
379 self.write(" ");
380 self.gen_condition(qualify);
381 }
382 }
383
384 if !sel.window_definitions.is_empty() {
385 self.sep();
386 self.write_keyword("WINDOW ");
387 for (i, wd) in sel.window_definitions.iter().enumerate() {
388 if i > 0 {
389 self.write(", ");
390 }
391 self.write(&wd.name);
392 self.write(" AS (");
393 self.gen_window_spec(&wd.spec);
394 self.write(")");
395 }
396 }
397
398 self.gen_order_by(&sel.order_by);
399
400 if let Some(limit) = &sel.limit {
401 self.sep();
402 self.write_keyword("LIMIT ");
403 self.gen_expr(limit);
404 }
405
406 if let Some(offset) = &sel.offset {
407 self.sep();
408 if matches!(
409 self.dialect,
410 Some(Dialect::Tsql) | Some(Dialect::Fabric) | Some(Dialect::Oracle)
411 ) {
412 self.write_keyword("OFFSET ");
413 self.gen_expr(offset);
414 self.write(" ");
415 self.write_keyword("ROWS");
416 } else {
417 self.write_keyword("OFFSET ");
418 self.gen_expr(offset);
419 }
420 }
421
422 if let Some(fetch) = &sel.fetch_first {
423 self.sep();
424 if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric)) {
425 self.write_keyword("FETCH NEXT ");
426 self.gen_expr(fetch);
427 self.write(" ");
428 self.write_keyword("ROWS ONLY");
429 } else {
430 self.write_keyword("FETCH FIRST ");
431 self.gen_expr(fetch);
432 self.write(" ");
433 self.write_keyword("ROWS ONLY");
434 }
435 }
436 }
437
438 fn gen_ctes(&mut self, ctes: &[Cte]) {
439 self.write_keyword("WITH ");
440 if ctes.iter().any(|c| c.recursive) {
441 self.write_keyword("RECURSIVE ");
442 }
443 for (i, cte) in ctes.iter().enumerate() {
444 if i > 0 {
445 self.write(",");
446 self.sep();
447 }
448 self.write_quoted(&cte.name, cte.name_quote_style);
449 if !cte.columns.is_empty() {
450 self.write("(");
451 self.write(&cte.columns.join(", "));
452 self.write(")");
453 }
454 self.write(" ");
455 self.write_keyword("AS ");
456 if let Some(true) = cte.materialized {
457 self.write_keyword("MATERIALIZED ");
458 } else if let Some(false) = cte.materialized {
459 self.write_keyword("NOT MATERIALIZED ");
460 }
461 self.write("(");
462 if self.pretty {
463 self.indent_up();
464 self.newline();
465 self.gen_statement(&cte.query);
466 self.indent_down();
467 self.newline();
468 } else {
469 self.gen_statement(&cte.query);
470 }
471 self.write(")");
472 }
473 }
474
475 fn gen_select_item(&mut self, item: &SelectItem) {
476 match item {
477 SelectItem::Wildcard => self.write("*"),
478 SelectItem::QualifiedWildcard { table } => {
479 self.write(table);
480 self.write(".*");
481 }
482 SelectItem::Expr {
483 expr,
484 alias,
485 alias_quote_style,
486 } => {
487 self.gen_expr(expr);
488 if let Some(alias) = alias {
489 self.write(" ");
490 self.write_keyword("AS ");
491 self.write_alias(alias, *alias_quote_style);
492 }
493 }
494 }
495 }
496
497 fn gen_table_source(&mut self, source: &TableSource) {
498 match source {
499 TableSource::Table(table_ref) => self.gen_table_ref(table_ref),
500 TableSource::Subquery {
501 query,
502 alias,
503 alias_quote_style,
504 } => {
505 self.write("(");
506 self.gen_statement(query);
507 self.write(")");
508 if let Some(alias) = alias {
509 self.write(" ");
510 if !self.omit_table_alias_as() {
511 self.write_keyword("AS ");
512 }
513 self.write_alias(alias, *alias_quote_style);
514 }
515 }
516 TableSource::TableFunction {
517 name,
518 args,
519 alias,
520 alias_quote_style,
521 } => {
522 self.write(name);
523 self.write("(");
524 self.gen_expr_list(args);
525 self.write(")");
526 if let Some(alias) = alias {
527 self.write(" ");
528 if !self.omit_table_alias_as() {
529 self.write_keyword("AS ");
530 }
531 self.write_alias(alias, *alias_quote_style);
532 }
533 }
534 TableSource::Lateral { source } => {
535 self.write_keyword("LATERAL ");
536 self.gen_table_source(source);
537 }
538 TableSource::Unnest {
539 expr,
540 alias,
541 alias_quote_style,
542 with_offset,
543 } => {
544 self.write_keyword("UNNEST(");
545 self.gen_expr(expr);
546 self.write(")");
547 if let Some(alias) = alias {
548 self.write(" ");
549 if !self.omit_table_alias_as() {
550 self.write_keyword("AS ");
551 }
552 self.write_quoted(alias, *alias_quote_style);
553 }
554 if *with_offset {
555 self.write(" ");
556 self.write_keyword("WITH OFFSET");
557 }
558 }
559 TableSource::Pivot {
560 source,
561 aggregate,
562 for_column,
563 in_values,
564 alias,
565 alias_quote_style,
566 } => {
567 self.gen_table_source(source);
568 self.write(" ");
569 self.write_keyword("PIVOT");
570 self.write(" (");
571 self.gen_expr(aggregate);
572 self.write(" ");
573 self.write_keyword("FOR ");
574 self.write(for_column);
575 self.write(" ");
576 self.write_keyword("IN ");
577 self.write("(");
578 self.gen_pivot_values(in_values);
579 self.write("))");
580 if let Some(alias) = alias {
581 self.write(" ");
582 if !self.omit_table_alias_as() {
583 self.write_keyword("AS ");
584 }
585 self.write_quoted(alias, *alias_quote_style);
586 }
587 }
588 TableSource::Unpivot {
589 source,
590 value_column,
591 for_column,
592 in_columns,
593 alias,
594 alias_quote_style,
595 } => {
596 self.gen_table_source(source);
597 self.write(" ");
598 self.write_keyword("UNPIVOT");
599 self.write(" (");
600 self.write(value_column);
601 self.write(" ");
602 self.write_keyword("FOR ");
603 self.write(for_column);
604 self.write(" ");
605 self.write_keyword("IN ");
606 self.write("(");
607 self.gen_pivot_values(in_columns);
608 self.write("))");
609 if let Some(alias) = alias {
610 self.write(" ");
611 if !self.omit_table_alias_as() {
612 self.write_keyword("AS ");
613 }
614 self.write_quoted(alias, *alias_quote_style);
615 }
616 }
617 }
618 }
619
620 fn gen_pivot_values(&mut self, values: &[PivotValue]) {
621 for (i, pv) in values.iter().enumerate() {
622 if i > 0 {
623 self.write(", ");
624 }
625 self.gen_expr(&pv.value);
626 if let Some(alias) = &pv.alias {
627 self.write(" ");
628 self.write_keyword("AS ");
629 self.write_alias(alias, pv.alias_quote_style);
630 }
631 }
632 }
633
634 fn omit_table_alias_as(&self) -> bool {
636 matches!(self.dialect, Some(Dialect::Oracle))
637 }
638
639 fn gen_table_ref(&mut self, table: &TableRef) {
640 if let Some(catalog) = &table.catalog {
641 self.write(catalog);
642 self.write(".");
643 }
644 if let Some(schema) = &table.schema {
645 self.write(schema);
646 self.write(".");
647 }
648 self.write_quoted(&table.name, table.name_quote_style);
649 if let Some(alias) = &table.alias {
650 self.write(" ");
651 if !self.omit_table_alias_as() {
652 self.write_keyword("AS ");
653 }
654 self.write_alias(alias, table.alias_quote_style);
655 }
656 }
657
658 fn gen_join(&mut self, join: &JoinClause) {
659 let join_kw = match join.join_type {
660 JoinType::Inner => "INNER JOIN",
661 JoinType::Left => "LEFT JOIN",
662 JoinType::Right => "RIGHT JOIN",
663 JoinType::Full => "FULL JOIN",
664 JoinType::Cross => "CROSS JOIN",
665 JoinType::Natural => "NATURAL JOIN",
666 JoinType::Lateral => "LATERAL JOIN",
667 };
668 self.sep();
669 self.write_keyword(join_kw);
670 if self.pretty {
671 self.indent_up();
672 self.newline();
673 self.gen_table_source(&join.table);
674 } else {
675 self.write(" ");
676 self.gen_table_source(&join.table);
677 }
678 if let Some(on) = &join.on {
679 if self.pretty {
680 self.newline();
681 } else {
682 self.write(" ");
683 }
684 self.write_keyword("ON ");
685 self.gen_condition(on);
686 }
687 if !join.using.is_empty() {
688 if self.pretty {
689 self.newline();
690 } else {
691 self.write(" ");
692 }
693 self.write_keyword("USING (");
694 self.write(&join.using.join(", "));
695 self.write(")");
696 }
697 if self.pretty {
698 self.indent_down();
699 }
700 }
701
702 fn gen_order_by_items_inline(&mut self, items: &[OrderByItem]) {
703 for (i, item) in items.iter().enumerate() {
704 if i > 0 {
705 self.write(", ");
706 }
707 self.gen_expr(&item.expr);
708 if !item.ascending {
709 self.write(" ");
710 self.write_keyword("DESC");
711 }
712 if let Some(nulls_first) = item.nulls_first {
713 if nulls_first {
714 self.write(" ");
715 self.write_keyword("NULLS FIRST");
716 } else {
717 self.write(" ");
718 self.write_keyword("NULLS LAST");
719 }
720 }
721 }
722 }
723
724 fn gen_order_by(&mut self, items: &[OrderByItem]) {
725 if items.is_empty() {
726 return;
727 }
728 self.sep();
729 self.write_keyword("ORDER BY");
730 if self.pretty {
731 self.indent_up();
732 self.newline();
733 } else {
734 self.write(" ");
735 }
736 for (i, item) in items.iter().enumerate() {
737 if i > 0 {
738 self.write(", ");
739 }
740 self.gen_expr(&item.expr);
741 if !item.ascending {
742 self.write(" ");
743 self.write_keyword("DESC");
744 }
745 if let Some(nulls_first) = item.nulls_first {
746 if nulls_first {
747 self.write(" ");
748 self.write_keyword("NULLS FIRST");
749 } else {
750 self.write(" ");
751 self.write_keyword("NULLS LAST");
752 }
753 }
754 }
755 if self.pretty {
756 self.indent_down();
757 }
758 }
759
760 fn gen_set_operation(&mut self, sop: &SetOperationStatement) {
763 self.gen_statement(&sop.left);
764 let op_kw = match sop.op {
765 SetOperationType::Union => "UNION",
766 SetOperationType::Intersect => "INTERSECT",
767 SetOperationType::Except => "EXCEPT",
768 };
769 self.sep();
770 self.write_keyword(op_kw);
771 if sop.all {
772 self.write(" ");
773 self.write_keyword("ALL");
774 }
775 self.sep();
776 self.gen_statement(&sop.right);
777
778 self.gen_order_by(&sop.order_by);
779
780 if let Some(limit) = &sop.limit {
781 self.sep();
782 self.write_keyword("LIMIT ");
783 self.gen_expr(limit);
784 }
785 if let Some(offset) = &sop.offset {
786 self.sep();
787 self.write_keyword("OFFSET ");
788 self.gen_expr(offset);
789 }
790 }
791
792 fn gen_insert(&mut self, ins: &InsertStatement) {
795 self.write_keyword("INSERT INTO ");
796 self.gen_table_ref(&ins.table);
797
798 if !ins.columns.is_empty() {
799 self.write(" (");
800 self.write(&ins.columns.join(", "));
801 self.write(")");
802 }
803
804 if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric))
806 && !ins.returning.is_empty()
807 {
808 self.sep();
809 self.gen_output_clause(&ins.returning, "INSERTED");
810 }
811
812 match &ins.source {
813 InsertSource::Values(rows) => {
814 self.sep();
815 self.write_keyword("VALUES");
816 if self.pretty {
817 self.indent_up();
818 for (i, row) in rows.iter().enumerate() {
819 self.newline();
820 self.write("(");
821 self.gen_expr_list(row);
822 self.write(")");
823 if i < rows.len() - 1 {
824 self.write(",");
825 }
826 }
827 self.indent_down();
828 } else {
829 self.write(" ");
830 for (i, row) in rows.iter().enumerate() {
831 if i > 0 {
832 self.write(", ");
833 }
834 self.write("(");
835 self.gen_expr_list(row);
836 self.write(")");
837 }
838 }
839 }
840 InsertSource::Query(query) => {
841 self.sep();
842 self.gen_statement(query);
843 }
844 InsertSource::Default => {
845 self.sep();
846 self.write_keyword("DEFAULT VALUES");
847 }
848 }
849
850 if let Some(on_conflict) = &ins.on_conflict {
851 self.sep();
852 self.write_keyword("ON CONFLICT");
853 if !on_conflict.columns.is_empty() {
854 self.write(" (");
855 self.write(&on_conflict.columns.join(", "));
856 self.write(")");
857 }
858 match &on_conflict.action {
859 ConflictAction::DoNothing => {
860 self.write(" ");
861 self.write_keyword("DO NOTHING");
862 }
863 ConflictAction::DoUpdate(assignments) => {
864 self.write(" ");
865 self.write_keyword("DO UPDATE SET ");
866 for (i, (col, val)) in assignments.iter().enumerate() {
867 if i > 0 {
868 self.write(", ");
869 }
870 self.write(col);
871 self.write(" = ");
872 self.gen_expr(val);
873 }
874 }
875 }
876 }
877
878 if !matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric))
880 && !ins.returning.is_empty()
881 {
882 self.sep();
883 self.write_keyword("RETURNING ");
884 for (i, item) in ins.returning.iter().enumerate() {
885 if i > 0 {
886 self.write(", ");
887 }
888 self.gen_select_item(item);
889 }
890 }
891 }
892
893 fn gen_update(&mut self, upd: &UpdateStatement) {
896 self.write_keyword("UPDATE ");
897 self.gen_table_ref(&upd.table);
898 self.sep();
899 self.write_keyword("SET");
900
901 if self.pretty {
902 self.indent_up();
903 for (i, (col, val)) in upd.assignments.iter().enumerate() {
904 self.newline();
905 self.write(col);
906 self.write(" = ");
907 self.gen_expr(val);
908 if i < upd.assignments.len() - 1 {
909 self.write(",");
910 }
911 }
912 self.indent_down();
913 } else {
914 self.write(" ");
915 for (i, (col, val)) in upd.assignments.iter().enumerate() {
916 if i > 0 {
917 self.write(", ");
918 }
919 self.write(col);
920 self.write(" = ");
921 self.gen_expr(val);
922 }
923 }
924
925 if let Some(from) = &upd.from {
926 self.sep();
927 self.write_keyword("FROM ");
928 self.gen_table_source(&from.source);
929 }
930
931 if let Some(wh) = &upd.where_clause {
932 self.sep();
933 self.write_keyword("WHERE");
934 if self.pretty {
935 self.indent_up();
936 self.newline();
937 self.gen_condition(wh);
938 self.indent_down();
939 } else {
940 self.write(" ");
941 self.gen_condition(wh);
942 }
943 }
944
945 if !upd.returning.is_empty() {
946 self.sep();
947 if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric)) {
948 self.gen_output_clause(&upd.returning, "INSERTED");
949 } else {
950 self.write_keyword("RETURNING ");
951 for (i, item) in upd.returning.iter().enumerate() {
952 if i > 0 {
953 self.write(", ");
954 }
955 self.gen_select_item(item);
956 }
957 }
958 }
959 }
960
961 fn gen_delete(&mut self, del: &DeleteStatement) {
964 self.write_keyword("DELETE FROM ");
965 self.gen_table_ref(&del.table);
966
967 if let Some(using) = &del.using {
968 self.sep();
969 self.write_keyword("USING ");
970 self.gen_table_source(&using.source);
971 }
972
973 if !del.returning.is_empty()
975 && matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric))
976 {
977 self.sep();
978 self.gen_output_clause(&del.returning, "DELETED");
979 }
980
981 if let Some(wh) = &del.where_clause {
982 self.sep();
983 self.write_keyword("WHERE");
984 if self.pretty {
985 self.indent_up();
986 self.newline();
987 self.gen_condition(wh);
988 self.indent_down();
989 } else {
990 self.write(" ");
991 self.gen_condition(wh);
992 }
993 }
994
995 if !del.returning.is_empty()
997 && !matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric))
998 {
999 self.sep();
1000 self.write_keyword("RETURNING ");
1001 for (i, item) in del.returning.iter().enumerate() {
1002 if i > 0 {
1003 self.write(", ");
1004 }
1005 self.gen_select_item(item);
1006 }
1007 }
1008 }
1009
1010 fn gen_output_clause(&mut self, items: &[SelectItem], prefix: &str) {
1014 self.write_keyword("OUTPUT ");
1015 for (i, item) in items.iter().enumerate() {
1016 if i > 0 {
1017 self.write(", ");
1018 }
1019 match item {
1020 SelectItem::Wildcard => {
1021 self.write(prefix);
1022 self.write(".*");
1023 }
1024 SelectItem::QualifiedWildcard { table } => {
1025 self.write(prefix);
1026 self.write(".");
1027 self.write(table);
1028 self.write(".*");
1029 }
1030 SelectItem::Expr { expr, .. } => match expr {
1031 Expr::Column { name, .. } => {
1032 self.write(prefix);
1033 self.write(".");
1034 self.write(name);
1035 }
1036 Expr::Star | Expr::Wildcard => {
1037 self.write(prefix);
1038 self.write(".*");
1039 }
1040 _ => {
1041 self.write(prefix);
1042 self.write(".");
1043 self.gen_expr(expr);
1044 }
1045 },
1046 }
1047 }
1048 }
1049
1050 fn gen_merge(&mut self, merge: &MergeStatement) {
1053 self.write_keyword("MERGE INTO ");
1054 self.gen_table_ref(&merge.target);
1055
1056 self.sep();
1057 self.write_keyword("USING ");
1058 self.gen_table_source(&merge.source);
1059
1060 self.sep();
1061 self.write_keyword("ON");
1062 if self.pretty {
1063 self.indent_up();
1064 self.newline();
1065 self.gen_expr(&merge.on);
1066 self.indent_down();
1067 } else {
1068 self.write(" ");
1069 self.gen_expr(&merge.on);
1070 }
1071
1072 for clause in &merge.clauses {
1073 self.sep();
1074 self.gen_merge_clause(clause);
1075 }
1076
1077 if !merge.output.is_empty() {
1078 self.sep();
1079 self.write_keyword("OUTPUT ");
1080 for (i, item) in merge.output.iter().enumerate() {
1081 if i > 0 {
1082 self.write(", ");
1083 }
1084 self.gen_select_item(item);
1085 }
1086 }
1087 }
1088
1089 fn gen_merge_clause(&mut self, clause: &MergeClause) {
1090 self.write_keyword("WHEN ");
1091 match &clause.kind {
1092 MergeClauseKind::Matched => self.write_keyword("MATCHED"),
1093 MergeClauseKind::NotMatched => self.write_keyword("NOT MATCHED"),
1094 MergeClauseKind::NotMatchedBySource => self.write_keyword("NOT MATCHED BY SOURCE"),
1095 }
1096
1097 if let Some(cond) = &clause.condition {
1098 self.write_keyword(" AND ");
1099 self.gen_condition(cond);
1100 }
1101
1102 self.write_keyword(" THEN");
1103
1104 match &clause.action {
1105 MergeAction::Update(assignments) => {
1106 self.sep();
1107 self.write_keyword("UPDATE SET");
1108 if self.pretty {
1109 self.indent_up();
1110 for (i, (col, val)) in assignments.iter().enumerate() {
1111 self.newline();
1112 self.write(col);
1113 self.write(" = ");
1114 self.gen_expr(val);
1115 if i < assignments.len() - 1 {
1116 self.write(",");
1117 }
1118 }
1119 self.indent_down();
1120 } else {
1121 self.write(" ");
1122 for (i, (col, val)) in assignments.iter().enumerate() {
1123 if i > 0 {
1124 self.write(", ");
1125 }
1126 self.write(col);
1127 self.write(" = ");
1128 self.gen_expr(val);
1129 }
1130 }
1131 }
1132 MergeAction::Insert { columns, values } => {
1133 self.sep();
1134 self.write_keyword("INSERT");
1135 if !columns.is_empty() {
1136 self.write(" (");
1137 self.write(&columns.join(", "));
1138 self.write(")");
1139 }
1140 self.write_keyword(" VALUES");
1141 self.write(" (");
1142 for (i, val) in values.iter().enumerate() {
1143 if i > 0 {
1144 self.write(", ");
1145 }
1146 self.gen_expr(val);
1147 }
1148 self.write(")");
1149 }
1150 MergeAction::InsertRow => {
1151 self.sep();
1152 self.write_keyword("INSERT ROW");
1153 }
1154 MergeAction::Delete => {
1155 self.sep();
1156 self.write_keyword("DELETE");
1157 }
1158 }
1159 }
1160
1161 fn gen_create_table(&mut self, ct: &CreateTableStatement) {
1164 self.write_keyword("CREATE ");
1165 if ct.temporary {
1166 self.write_keyword("TEMPORARY ");
1167 }
1168 self.write_keyword("TABLE ");
1169 if ct.if_not_exists {
1170 self.write_keyword("IF NOT EXISTS ");
1171 }
1172 self.gen_table_ref(&ct.table);
1173
1174 if let Some(as_select) = &ct.as_select {
1175 self.write(" ");
1176 self.write_keyword("AS ");
1177 self.gen_statement(as_select);
1178 return;
1179 }
1180
1181 self.write(" (");
1182
1183 if self.pretty {
1184 self.indent_up();
1185 for (i, col) in ct.columns.iter().enumerate() {
1186 self.newline();
1187 self.gen_column_def(col);
1188 if i < ct.columns.len() - 1 || !ct.constraints.is_empty() {
1189 self.write(",");
1190 }
1191 }
1192 for (i, constraint) in ct.constraints.iter().enumerate() {
1193 self.newline();
1194 self.gen_table_constraint(constraint);
1195 if i < ct.constraints.len() - 1 {
1196 self.write(",");
1197 }
1198 }
1199 self.indent_down();
1200 self.newline();
1201 } else {
1202 for (i, col) in ct.columns.iter().enumerate() {
1203 if i > 0 {
1204 self.write(", ");
1205 }
1206 self.gen_column_def(col);
1207 }
1208 for (i, constraint) in ct.constraints.iter().enumerate() {
1209 if i + ct.columns.len() > 0 {
1210 self.write(", ");
1211 }
1212 self.gen_table_constraint(constraint);
1213 }
1214 }
1215
1216 self.write(")");
1217 }
1218
1219 fn gen_column_def(&mut self, col: &ColumnDef) {
1220 self.write(&col.name);
1221 self.write(" ");
1222 self.gen_data_type(&col.data_type);
1223
1224 if col.primary_key {
1225 self.write(" ");
1226 self.write_keyword("PRIMARY KEY");
1227 }
1228 if col.unique {
1229 self.write(" ");
1230 self.write_keyword("UNIQUE");
1231 }
1232 if col.auto_increment {
1233 self.write(" ");
1234 self.write_keyword("AUTOINCREMENT");
1235 }
1236
1237 match col.nullable {
1238 Some(false) => {
1239 self.write(" ");
1240 self.write_keyword("NOT NULL");
1241 }
1242 Some(true) => {
1243 self.write(" ");
1244 self.write_keyword("NULL");
1245 }
1246 None => {}
1247 }
1248
1249 if let Some(default) = &col.default {
1250 self.write(" ");
1251 self.write_keyword("DEFAULT ");
1252 self.gen_expr(default);
1253 }
1254
1255 if let Some(collation) = &col.collation {
1256 self.write(" ");
1257 self.write_keyword("COLLATE ");
1258 self.write(collation);
1259 }
1260
1261 if let Some(comment) = &col.comment {
1262 self.write(" ");
1263 self.write_keyword("COMMENT '");
1264 self.write(&comment.replace('\'', "''"));
1265 self.write("'");
1266 }
1267 }
1268
1269 fn gen_table_constraint(&mut self, constraint: &TableConstraint) {
1270 match constraint {
1271 TableConstraint::PrimaryKey { name, columns } => {
1272 if let Some(name) = name {
1273 self.write_keyword("CONSTRAINT ");
1274 self.write(name);
1275 self.write(" ");
1276 }
1277 self.write_keyword("PRIMARY KEY (");
1278 self.write(&columns.join(", "));
1279 self.write(")");
1280 }
1281 TableConstraint::Unique { name, columns } => {
1282 if let Some(name) = name {
1283 self.write_keyword("CONSTRAINT ");
1284 self.write(name);
1285 self.write(" ");
1286 }
1287 self.write_keyword("UNIQUE (");
1288 self.write(&columns.join(", "));
1289 self.write(")");
1290 }
1291 TableConstraint::ForeignKey {
1292 name,
1293 columns,
1294 ref_table,
1295 ref_columns,
1296 on_delete,
1297 on_update,
1298 } => {
1299 if let Some(name) = name {
1300 self.write_keyword("CONSTRAINT ");
1301 self.write(name);
1302 self.write(" ");
1303 }
1304 self.write_keyword("FOREIGN KEY (");
1305 self.write(&columns.join(", "));
1306 self.write(") ");
1307 self.write_keyword("REFERENCES ");
1308 self.gen_table_ref(ref_table);
1309 self.write(" (");
1310 self.write(&ref_columns.join(", "));
1311 self.write(")");
1312 if let Some(action) = on_delete {
1313 self.write(" ");
1314 self.write_keyword("ON DELETE ");
1315 self.gen_referential_action(action);
1316 }
1317 if let Some(action) = on_update {
1318 self.write(" ");
1319 self.write_keyword("ON UPDATE ");
1320 self.gen_referential_action(action);
1321 }
1322 }
1323 TableConstraint::Check { name, expr } => {
1324 if let Some(name) = name {
1325 self.write_keyword("CONSTRAINT ");
1326 self.write(name);
1327 self.write(" ");
1328 }
1329 self.write_keyword("CHECK (");
1330 self.gen_expr(expr);
1331 self.write(")");
1332 }
1333 }
1334 }
1335
1336 fn gen_referential_action(&mut self, action: &ReferentialAction) {
1337 match action {
1338 ReferentialAction::Cascade => self.write_keyword("CASCADE"),
1339 ReferentialAction::Restrict => self.write_keyword("RESTRICT"),
1340 ReferentialAction::NoAction => self.write_keyword("NO ACTION"),
1341 ReferentialAction::SetNull => self.write_keyword("SET NULL"),
1342 ReferentialAction::SetDefault => self.write_keyword("SET DEFAULT"),
1343 }
1344 }
1345
1346 fn gen_drop_table(&mut self, dt: &DropTableStatement) {
1349 self.write_keyword("DROP TABLE ");
1350 if dt.if_exists {
1351 self.write_keyword("IF EXISTS ");
1352 }
1353 self.gen_table_ref(&dt.table);
1354 if dt.cascade {
1355 self.write(" ");
1356 self.write_keyword("CASCADE");
1357 }
1358 }
1359
1360 fn gen_alter_table(&mut self, alt: &AlterTableStatement) {
1363 self.write_keyword("ALTER TABLE ");
1364 self.gen_table_ref(&alt.table);
1365
1366 for (i, action) in alt.actions.iter().enumerate() {
1367 if i > 0 {
1368 self.write(",");
1369 }
1370 self.write(" ");
1371 match action {
1372 AlterTableAction::AddColumn(col) => {
1373 self.write_keyword("ADD COLUMN ");
1374 self.gen_column_def(col);
1375 }
1376 AlterTableAction::DropColumn { name, if_exists } => {
1377 self.write_keyword("DROP COLUMN ");
1378 if *if_exists {
1379 self.write_keyword("IF EXISTS ");
1380 }
1381 self.write(name);
1382 }
1383 AlterTableAction::RenameColumn { old_name, new_name } => {
1384 self.write_keyword("RENAME COLUMN ");
1385 self.write(old_name);
1386 self.write(" ");
1387 self.write_keyword("TO ");
1388 self.write(new_name);
1389 }
1390 AlterTableAction::AlterColumnType { name, data_type } => {
1391 self.write_keyword("ALTER COLUMN ");
1392 self.write(name);
1393 self.write(" ");
1394 self.write_keyword("TYPE ");
1395 self.gen_data_type(data_type);
1396 }
1397 AlterTableAction::AddConstraint(constraint) => {
1398 self.write_keyword("ADD ");
1399 self.gen_table_constraint(constraint);
1400 }
1401 AlterTableAction::DropConstraint { name } => {
1402 self.write_keyword("DROP CONSTRAINT ");
1403 self.write(name);
1404 }
1405 AlterTableAction::RenameTable { new_name } => {
1406 self.write_keyword("RENAME TO ");
1407 self.write(new_name);
1408 }
1409 }
1410 }
1411 }
1412
1413 fn gen_create_view(&mut self, cv: &CreateViewStatement) {
1416 self.write_keyword("CREATE ");
1417 if cv.or_replace {
1418 self.write_keyword("OR REPLACE ");
1419 }
1420 if cv.materialized {
1421 self.write_keyword("MATERIALIZED ");
1422 }
1423 self.write_keyword("VIEW ");
1424 if cv.if_not_exists {
1425 self.write_keyword("IF NOT EXISTS ");
1426 }
1427 self.gen_table_ref(&cv.name);
1428
1429 if !cv.columns.is_empty() {
1430 self.write(" (");
1431 self.write(&cv.columns.join(", "));
1432 self.write(")");
1433 }
1434
1435 self.write(" ");
1436 self.write_keyword("AS ");
1437 self.gen_statement(&cv.query);
1438 }
1439
1440 fn gen_drop_view(&mut self, dv: &DropViewStatement) {
1441 self.write_keyword("DROP ");
1442 if dv.materialized {
1443 self.write_keyword("MATERIALIZED ");
1444 }
1445 self.write_keyword("VIEW ");
1446 if dv.if_exists {
1447 self.write_keyword("IF EXISTS ");
1448 }
1449 self.gen_table_ref(&dv.name);
1450 }
1451
1452 fn gen_truncate(&mut self, t: &TruncateStatement) {
1455 self.write_keyword("TRUNCATE TABLE ");
1456 self.gen_table_ref(&t.table);
1457 }
1458
1459 fn gen_transaction(&mut self, t: &TransactionStatement) {
1462 match t {
1463 TransactionStatement::Begin => self.write_keyword("BEGIN"),
1464 TransactionStatement::Commit => self.write_keyword("COMMIT"),
1465 TransactionStatement::Rollback => self.write_keyword("ROLLBACK"),
1466 TransactionStatement::Savepoint(name) => {
1467 self.write_keyword("SAVEPOINT ");
1468 self.write(name);
1469 }
1470 TransactionStatement::ReleaseSavepoint(name) => {
1471 self.write_keyword("RELEASE SAVEPOINT ");
1472 self.write(name);
1473 }
1474 TransactionStatement::RollbackTo(name) => {
1475 self.write_keyword("ROLLBACK TO SAVEPOINT ");
1476 self.write(name);
1477 }
1478 }
1479 }
1480
1481 fn gen_explain(&mut self, e: &ExplainStatement) {
1484 self.write_keyword("EXPLAIN ");
1485 if e.analyze {
1486 self.write_keyword("ANALYZE ");
1487 }
1488 self.gen_statement(&e.statement);
1489 }
1490
1491 fn gen_use(&mut self, u: &UseStatement) {
1494 self.write_keyword("USE ");
1495 self.write(&u.name);
1496 }
1497
1498 fn gen_data_type(&mut self, dt: &DataType) {
1503 match dt {
1504 DataType::TinyInt => self.write("TINYINT"),
1505 DataType::SmallInt => self.write("SMALLINT"),
1506 DataType::Int => self.write("INT"),
1507 DataType::BigInt => self.write("BIGINT"),
1508 DataType::Float => self.write("FLOAT"),
1509 DataType::Double => self.write("DOUBLE"),
1510 DataType::Real => self.write("REAL"),
1511 DataType::Decimal { precision, scale } | DataType::Numeric { precision, scale } => {
1512 self.write(if matches!(dt, DataType::Numeric { .. }) {
1513 "NUMERIC"
1514 } else {
1515 "DECIMAL"
1516 });
1517 if let Some(p) = precision {
1518 self.write(&format!("({p}"));
1519 if let Some(s) = scale {
1520 self.write(&format!(", {s}"));
1521 }
1522 self.write(")");
1523 }
1524 }
1525 DataType::Varchar(len) => {
1526 self.write("VARCHAR");
1527 if let Some(n) = len {
1528 self.write(&format!("({n})"));
1529 }
1530 }
1531 DataType::Char(len) => {
1532 self.write("CHAR");
1533 if let Some(n) = len {
1534 self.write(&format!("({n})"));
1535 }
1536 }
1537 DataType::Text => self.write("TEXT"),
1538 DataType::String => self.write("STRING"),
1539 DataType::Binary(len) => {
1540 self.write("BINARY");
1541 if let Some(n) = len {
1542 self.write(&format!("({n})"));
1543 }
1544 }
1545 DataType::Varbinary(len) => {
1546 self.write("VARBINARY");
1547 match len {
1548 Some(n) => self.write(&format!("({n})")),
1549 None if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric)) => {
1550 self.write("(MAX)");
1551 }
1552 None => {}
1553 }
1554 }
1555 DataType::Boolean => self.write("BOOLEAN"),
1556 DataType::Date => self.write("DATE"),
1557 DataType::Time { precision } => {
1558 self.write("TIME");
1559 if let Some(p) = precision {
1560 self.write(&format!("({p})"));
1561 }
1562 }
1563 DataType::Timestamp { precision, with_tz } => {
1564 self.write("TIMESTAMP");
1565 if let Some(p) = precision {
1566 self.write(&format!("({p})"));
1567 }
1568 if *with_tz {
1569 self.write(" WITH TIME ZONE");
1570 }
1571 }
1572 DataType::Interval => self.write("INTERVAL"),
1573 DataType::DateTime => self.write("DATETIME"),
1574 DataType::Blob => self.write("BLOB"),
1575 DataType::Bytea => self.write("BYTEA"),
1576 DataType::Bytes => self.write("BYTES"),
1577 DataType::Json => self.write("JSON"),
1578 DataType::Jsonb => self.write("JSONB"),
1579 DataType::Uuid => self.write("UUID"),
1580 DataType::Array(inner) => {
1581 let is_postgres = matches!(
1582 self.dialect,
1583 Some(
1584 Dialect::Postgres
1585 | Dialect::Redshift
1586 | Dialect::Materialize
1587 | Dialect::RisingWave
1588 )
1589 );
1590 if is_postgres {
1591 if let Some(inner) = inner {
1593 self.gen_data_type(inner);
1594 self.write("[]");
1595 } else {
1596 self.write("ARRAY");
1597 }
1598 } else {
1599 self.write("ARRAY");
1600 if let Some(inner) = inner {
1601 self.write("<");
1602 self.gen_data_type(inner);
1603 self.write(">");
1604 }
1605 }
1606 }
1607 DataType::Map { key, value } => {
1608 self.write("MAP<");
1609 self.gen_data_type(key);
1610 self.write(", ");
1611 self.gen_data_type(value);
1612 self.write(">");
1613 }
1614 DataType::Struct(fields) => {
1615 self.write("STRUCT<");
1616 for (i, (name, dt)) in fields.iter().enumerate() {
1617 if i > 0 {
1618 self.write(", ");
1619 }
1620 self.write(name);
1621 self.write(" ");
1622 self.gen_data_type(dt);
1623 }
1624 self.write(">");
1625 }
1626 DataType::Tuple(types) => {
1627 self.write("TUPLE(");
1628 for (i, dt) in types.iter().enumerate() {
1629 if i > 0 {
1630 self.write(", ");
1631 }
1632 self.gen_data_type(dt);
1633 }
1634 self.write(")");
1635 }
1636 DataType::Null => self.write("NULL"),
1637 DataType::Variant => self.write("VARIANT"),
1638 DataType::Object => self.write("OBJECT"),
1639 DataType::Xml => self.write("XML"),
1640 DataType::Inet => self.write("INET"),
1641 DataType::Cidr => self.write("CIDR"),
1642 DataType::Macaddr => self.write("MACADDR"),
1643 DataType::Bit(len) => {
1644 self.write("BIT");
1645 if let Some(n) = len {
1646 self.write(&format!("({n})"));
1647 }
1648 }
1649 DataType::Money => self.write("MONEY"),
1650 DataType::Serial => self.write("SERIAL"),
1651 DataType::BigSerial => self.write("BIGSERIAL"),
1652 DataType::SmallSerial => self.write("SMALLSERIAL"),
1653 DataType::Regclass => self.write("REGCLASS"),
1654 DataType::Regtype => self.write("REGTYPE"),
1655 DataType::Hstore => self.write("HSTORE"),
1656 DataType::Geography => self.write("GEOGRAPHY"),
1657 DataType::Geometry => self.write("GEOMETRY"),
1658 DataType::Super => self.write("SUPER"),
1659 DataType::Unknown(name) => self.write(name),
1660 }
1661 }
1662
1663 fn binary_op_str(op: &BinaryOperator) -> &'static str {
1668 match op {
1669 BinaryOperator::Plus => " + ",
1670 BinaryOperator::Minus => " - ",
1671 BinaryOperator::Multiply => " * ",
1672 BinaryOperator::Divide => " / ",
1673 BinaryOperator::Modulo => " % ",
1674 BinaryOperator::Eq => " = ",
1675 BinaryOperator::Neq => " <> ",
1676 BinaryOperator::Lt => " < ",
1677 BinaryOperator::Gt => " > ",
1678 BinaryOperator::LtEq => " <= ",
1679 BinaryOperator::GtEq => " >= ",
1680 BinaryOperator::And => " AND ",
1681 BinaryOperator::Or => " OR ",
1682 BinaryOperator::Xor => " XOR ",
1683 BinaryOperator::Concat => " || ",
1684 BinaryOperator::BitwiseAnd => " & ",
1685 BinaryOperator::BitwiseOr => " | ",
1686 BinaryOperator::BitwiseXor => " ^ ",
1687 BinaryOperator::ShiftLeft => " << ",
1688 BinaryOperator::ShiftRight => " >> ",
1689 BinaryOperator::Arrow => " -> ",
1690 BinaryOperator::DoubleArrow => " ->> ",
1691 BinaryOperator::AtArrow => " @> ",
1692 BinaryOperator::ArrowAt => " <@ ",
1693 }
1694 }
1695
1696 fn gen_expr_list(&mut self, exprs: &[Expr]) {
1697 for (i, expr) in exprs.iter().enumerate() {
1698 if i > 0 {
1699 self.write(", ");
1700 }
1701 self.gen_expr(expr);
1702 }
1703 }
1704
1705 fn gen_condition(&mut self, e: &Expr) {
1719 if !matches!(self.dialect, Some(d) if crate::dialects::is_tsql_family(d)) {
1720 self.gen_expr(e);
1721 return;
1722 }
1723 match e {
1724 Expr::BinaryOp { left, op, right }
1726 if matches!(
1727 op,
1728 BinaryOperator::And | BinaryOperator::Or | BinaryOperator::Xor
1729 ) =>
1730 {
1731 self.gen_condition(left);
1732 self.write(Self::binary_op_str(op));
1733 self.gen_condition(right);
1734 }
1735 Expr::UnaryOp {
1736 op: UnaryOperator::Not,
1737 expr,
1738 } => {
1739 self.write("NOT ");
1740 self.gen_condition(expr);
1741 }
1742 Expr::Nested(inner) => {
1743 self.write("(");
1744 self.gen_condition(inner);
1745 self.write(")");
1746 }
1747 Expr::BinaryOp {
1749 op:
1750 BinaryOperator::Eq
1751 | BinaryOperator::Neq
1752 | BinaryOperator::Lt
1753 | BinaryOperator::Gt
1754 | BinaryOperator::LtEq
1755 | BinaryOperator::GtEq,
1756 ..
1757 }
1758 | Expr::Between { .. }
1759 | Expr::IsNull { .. }
1760 | Expr::IsBool { .. }
1761 | Expr::InList { .. }
1762 | Expr::InSubquery { .. }
1763 | Expr::Like { .. }
1764 | Expr::ILike { .. }
1765 | Expr::SimilarTo { .. }
1766 | Expr::Exists { .. }
1767 | Expr::AnyOp { .. }
1768 | Expr::AllOp { .. } => self.gen_expr(e),
1769 Expr::Boolean(b) => self.write(if *b { "1 = 1" } else { "1 = 0" }),
1771 _ => {
1774 self.gen_expr(e);
1775 self.write(" = 1");
1776 }
1777 }
1778 }
1779
1780 fn gen_expr(&mut self, expr: &Expr) {
1781 match expr {
1782 Expr::Column {
1783 table,
1784 name,
1785 quote_style,
1786 table_quote_style,
1787 } => {
1788 if let Some(t) = table {
1789 self.write_quoted(t, *table_quote_style);
1790 self.write(".");
1791 }
1792 self.write_quoted(name, *quote_style);
1793 }
1794 Expr::Number(n) => self.write(n),
1795 Expr::StringLiteral(s) => {
1796 if matches!(self.dialect, Some(Dialect::Oracle) | Some(Dialect::Tsql))
1799 && !s.is_ascii()
1800 {
1801 self.write("N'");
1802 } else {
1803 self.write("'");
1804 }
1805 self.write(&s.replace('\'', "''"));
1806 self.write("'");
1807 }
1808 Expr::NationalStringLiteral(s) => {
1809 if matches!(self.dialect, Some(Dialect::Oracle) | Some(Dialect::Tsql)) {
1810 self.write("N'");
1811 } else {
1812 self.write("'");
1813 }
1814 self.write(&s.replace('\'', "''"));
1815 self.write("'");
1816 }
1817 Expr::Boolean(b) => {
1818 if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric)) {
1819 self.write(if *b { "1" } else { "0" });
1820 } else {
1821 self.write(if *b { "TRUE" } else { "FALSE" });
1822 }
1823 }
1824 Expr::Null => self.write("NULL"),
1825 Expr::Default => self.write_keyword("DEFAULT"),
1826 Expr::Wildcard | Expr::Star => self.write("*"),
1827
1828 Expr::Cube { exprs } => {
1829 self.write_keyword("CUBE");
1830 self.write("(");
1831 self.gen_expr_list(exprs);
1832 self.write(")");
1833 }
1834 Expr::Rollup { exprs } => {
1835 self.write_keyword("ROLLUP");
1836 self.write("(");
1837 self.gen_expr_list(exprs);
1838 self.write(")");
1839 }
1840 Expr::GroupingSets { sets } => {
1841 self.write_keyword("GROUPING SETS");
1842 self.write("(");
1843 self.gen_expr_list(sets);
1844 self.write(")");
1845 }
1846
1847 Expr::BinaryOp { left, op, right } => {
1848 self.gen_expr(left);
1849 self.write(Self::binary_op_str(op));
1850 self.gen_expr(right);
1851 }
1852 Expr::AnyOp { expr, op, right } => {
1853 self.gen_expr(expr);
1854 self.write(Self::binary_op_str(op));
1855 self.write_keyword("ANY");
1856 self.write("(");
1857 if let Expr::Subquery(query) = right.as_ref() {
1858 self.gen_statement(query);
1859 } else {
1860 self.gen_expr(right);
1861 }
1862 self.write(")");
1863 }
1864 Expr::AllOp { expr, op, right } => {
1865 self.gen_expr(expr);
1866 self.write(Self::binary_op_str(op));
1867 self.write_keyword("ALL");
1868 self.write("(");
1869 if let Expr::Subquery(query) = right.as_ref() {
1870 self.gen_statement(query);
1871 } else {
1872 self.gen_expr(right);
1873 }
1874 self.write(")");
1875 }
1876 Expr::UnaryOp { op, expr } => {
1877 let op_str = match op {
1878 UnaryOperator::Not => "NOT ",
1879 UnaryOperator::Minus => "-",
1880 UnaryOperator::Plus => "+",
1881 UnaryOperator::BitwiseNot => "~",
1882 };
1883 self.write(op_str);
1884 self.gen_expr(expr);
1885 }
1886 Expr::Function {
1887 name,
1888 args,
1889 distinct,
1890 filter,
1891 over,
1892 order_by,
1893 within_group,
1894 } => {
1895 self.write(name);
1896 self.write("(");
1897 if *distinct {
1898 self.write_keyword("DISTINCT ");
1899 }
1900 self.gen_expr_list(args);
1901 if !*within_group && !order_by.is_empty() {
1903 self.write(" ");
1904 self.write_keyword("ORDER BY ");
1905 self.gen_order_by_items_inline(order_by);
1906 }
1907 self.write(")");
1908
1909 if *within_group && !order_by.is_empty() {
1911 self.write(" ");
1912 self.write_keyword("WITHIN GROUP (ORDER BY ");
1913 self.gen_order_by_items_inline(order_by);
1914 self.write(")");
1915 }
1916
1917 if let Some(filter_expr) = filter {
1918 self.write(" ");
1919 self.write_keyword("FILTER (WHERE ");
1920 self.gen_expr(filter_expr);
1921 self.write(")");
1922 }
1923 if let Some(spec) = over {
1924 self.write(" ");
1925 self.write_keyword("OVER ");
1926 if let Some(wref) = &spec.window_ref {
1927 if spec.partition_by.is_empty()
1928 && spec.order_by.is_empty()
1929 && spec.frame.is_none()
1930 {
1931 self.write(wref);
1932 } else {
1933 self.write("(");
1934 self.gen_window_spec(spec);
1935 self.write(")");
1936 }
1937 } else {
1938 self.write("(");
1939 self.gen_window_spec(spec);
1940 self.write(")");
1941 }
1942 }
1943 }
1944 Expr::Between {
1945 expr,
1946 low,
1947 high,
1948 negated,
1949 } => {
1950 self.gen_expr(expr);
1951 if *negated {
1952 self.write(" ");
1953 self.write_keyword("NOT");
1954 }
1955 self.write(" ");
1956 self.write_keyword("BETWEEN ");
1957 self.gen_expr(low);
1958 self.write(" ");
1959 self.write_keyword("AND ");
1960 self.gen_expr(high);
1961 }
1962 Expr::InList {
1963 expr,
1964 list,
1965 negated,
1966 } => {
1967 self.gen_expr(expr);
1968 if *negated {
1969 self.write(" ");
1970 self.write_keyword("NOT");
1971 }
1972 self.write(" ");
1973 self.write_keyword("IN (");
1974 self.gen_expr_list(list);
1975 self.write(")");
1976 }
1977 Expr::InSubquery {
1978 expr,
1979 subquery,
1980 negated,
1981 } => {
1982 self.gen_expr(expr);
1983 if *negated {
1984 self.write(" ");
1985 self.write_keyword("NOT");
1986 }
1987 self.write(" ");
1988 self.write_keyword("IN (");
1989 self.gen_statement(subquery);
1990 self.write(")");
1991 }
1992 Expr::IsNull { expr, negated } => {
1993 self.gen_expr(expr);
1994 if *negated {
1995 self.write(" ");
1996 self.write_keyword("IS NOT NULL");
1997 } else {
1998 self.write(" ");
1999 self.write_keyword("IS NULL");
2000 }
2001 }
2002 Expr::IsBool {
2003 expr,
2004 value,
2005 negated,
2006 } => {
2007 self.gen_expr(expr);
2008 self.write(" ");
2009 match (negated, value) {
2010 (false, true) => self.write_keyword("IS TRUE"),
2011 (false, false) => self.write_keyword("IS FALSE"),
2012 (true, true) => self.write_keyword("IS NOT TRUE"),
2013 (true, false) => self.write_keyword("IS NOT FALSE"),
2014 }
2015 }
2016 Expr::Like {
2017 expr,
2018 pattern,
2019 negated,
2020 escape,
2021 } => {
2022 self.gen_expr(expr);
2023 if *negated {
2024 self.write(" ");
2025 self.write_keyword("NOT");
2026 }
2027 self.write(" ");
2028 self.write_keyword("LIKE ");
2029 self.gen_expr(pattern);
2030 if let Some(esc) = escape {
2031 self.write(" ");
2032 self.write_keyword("ESCAPE ");
2033 self.gen_expr(esc);
2034 }
2035 }
2036 Expr::ILike {
2037 expr,
2038 pattern,
2039 negated,
2040 escape,
2041 } => {
2042 self.gen_expr(expr);
2043 if *negated {
2044 self.write(" ");
2045 self.write_keyword("NOT");
2046 }
2047 self.write(" ");
2048 self.write_keyword("ILIKE ");
2049 self.gen_expr(pattern);
2050 if let Some(esc) = escape {
2051 self.write(" ");
2052 self.write_keyword("ESCAPE ");
2053 self.gen_expr(esc);
2054 }
2055 }
2056 Expr::SimilarTo {
2057 expr,
2058 pattern,
2059 negated,
2060 escape,
2061 } => {
2062 self.gen_expr(expr);
2063 if *negated {
2064 self.write(" ");
2065 self.write_keyword("NOT");
2066 }
2067 self.write(" ");
2068 self.write_keyword("SIMILAR TO ");
2069 self.gen_expr(pattern);
2070 if let Some(esc) = escape {
2071 self.write(" ");
2072 self.write_keyword("ESCAPE ");
2073 self.gen_expr(esc);
2074 }
2075 }
2076 Expr::Case {
2077 operand,
2078 when_clauses,
2079 else_clause,
2080 } => {
2081 self.write_keyword("CASE");
2082 if let Some(op) = operand {
2083 self.write(" ");
2084 self.gen_expr(op);
2085 }
2086 for (cond, result) in when_clauses {
2087 self.write(" ");
2088 self.write_keyword("WHEN ");
2089 if operand.is_some() {
2094 self.gen_expr(cond);
2095 } else {
2096 self.gen_condition(cond);
2097 }
2098 self.write(" ");
2099 self.write_keyword("THEN ");
2100 self.gen_expr(result);
2101 }
2102 if let Some(el) = else_clause {
2103 self.write(" ");
2104 self.write_keyword("ELSE ");
2105 self.gen_expr(el);
2106 }
2107 self.write(" ");
2108 self.write_keyword("END");
2109 }
2110 Expr::Nested(inner) => {
2111 self.write("(");
2112 self.gen_expr(inner);
2113 self.write(")");
2114 }
2115 Expr::Subquery(query) => {
2116 self.write("(");
2117 self.gen_statement(query);
2118 self.write(")");
2119 }
2120 Expr::Exists { subquery, negated } => {
2121 if *negated {
2122 self.write_keyword("NOT ");
2123 }
2124 self.write_keyword("EXISTS (");
2125 self.gen_statement(subquery);
2126 self.write(")");
2127 }
2128 Expr::Cast { expr, data_type } => {
2129 if let Expr::StringLiteral(val) = expr.as_ref() {
2131 let ansi_keyword = match data_type {
2132 DataType::Date => Some("DATE"),
2133 DataType::Timestamp { .. } => Some("TIMESTAMP"),
2134 DataType::Time { .. } => Some("TIME"),
2135 _ => None,
2136 };
2137 if let Some(kw) = ansi_keyword {
2138 let ansi_typed_literal_unsupported = matches!(
2145 self.dialect,
2146 Some(
2147 Dialect::Mysql
2148 | Dialect::Doris
2149 | Dialect::SingleStore
2150 | Dialect::StarRocks
2151 | Dialect::Tsql
2152 | Dialect::Fabric
2153 )
2154 );
2155 if !ansi_typed_literal_unsupported {
2156 self.write_keyword(kw);
2157 self.write(" '");
2158 self.write(val);
2159 self.write("'");
2160 return;
2161 }
2162 }
2163 }
2164
2165 let is_postgres = matches!(
2166 self.dialect,
2167 Some(
2168 Dialect::Postgres
2169 | Dialect::Redshift
2170 | Dialect::Materialize
2171 | Dialect::RisingWave
2172 )
2173 );
2174 if is_postgres {
2175 self.gen_expr(expr);
2176 self.write("::");
2177 self.gen_data_type(data_type);
2178 } else {
2179 self.write_keyword("CAST(");
2180 self.gen_expr(expr);
2181 self.write(" ");
2182 self.write_keyword("AS ");
2183 self.gen_data_type(data_type);
2184 self.write(")");
2185 }
2186 }
2187 Expr::TryCast { expr, data_type } => {
2188 self.write_keyword("TRY_CAST(");
2189 self.gen_expr(expr);
2190 self.write(" ");
2191 self.write_keyword("AS ");
2192 self.gen_data_type(data_type);
2193 self.write(")");
2194 }
2195 Expr::Extract { field, expr } => {
2196 if matches!(self.dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric)) {
2197 match field {
2198 DateTimeField::Epoch => {
2199 self.write_keyword("DATEDIFF(SECOND, '1970-01-01', ");
2201 self.gen_expr(expr);
2202 self.write(")");
2203 }
2204 DateTimeField::DayOfWeek => {
2205 self.write_keyword("(DATEPART(WEEKDAY, ");
2210 self.gen_expr(expr);
2211 self.write_keyword(") + @@DATEFIRST - 1) % 7");
2212 }
2213 _ => {
2214 self.write_keyword("DATEPART(");
2215 match field {
2216 DateTimeField::DayOfYear => self.write("DAYOFYEAR"),
2218 DateTimeField::Week => self.write("ISO_WEEK"),
2220 _ => self.gen_datetime_field(field),
2226 }
2227 self.write(", ");
2228 self.gen_expr(expr);
2229 self.write(")");
2230 }
2231 }
2232 } else {
2233 self.write_keyword("EXTRACT(");
2234 self.gen_datetime_field(field);
2235 self.write(" ");
2236 self.write_keyword("FROM ");
2237 self.gen_expr(expr);
2238 self.write(")");
2239 }
2240 }
2241 Expr::Interval { value, unit } => {
2242 self.write_keyword("INTERVAL ");
2243 self.gen_expr(value);
2244 if let Some(unit) = unit {
2245 self.write(" ");
2246 self.gen_datetime_field(unit);
2247 }
2248 }
2249 Expr::ArrayLiteral(items) => {
2250 self.write_keyword("ARRAY[");
2251 self.gen_expr_list(items);
2252 self.write("]");
2253 }
2254 Expr::Tuple(items) => {
2255 self.write("(");
2256 self.gen_expr_list(items);
2257 self.write(")");
2258 }
2259 Expr::Coalesce(items) => {
2260 self.write_keyword("COALESCE(");
2261 self.gen_expr_list(items);
2262 self.write(")");
2263 }
2264 Expr::If {
2265 condition,
2266 true_val,
2267 false_val,
2268 } => {
2269 self.write_keyword("IF(");
2270 self.gen_expr(condition);
2271 self.write(", ");
2272 self.gen_expr(true_val);
2273 if let Some(fv) = false_val {
2274 self.write(", ");
2275 self.gen_expr(fv);
2276 }
2277 self.write(")");
2278 }
2279 Expr::NullIf { expr, r#else } => {
2280 self.write_keyword("NULLIF(");
2281 self.gen_expr(expr);
2282 self.write(", ");
2283 self.gen_expr(r#else);
2284 self.write(")");
2285 }
2286 Expr::Collate { expr, collation } => {
2287 self.gen_expr(expr);
2288 self.write(" ");
2289 self.write_keyword("COLLATE ");
2290 self.write(collation);
2291 }
2292 Expr::Parameter(p) => self.write(p),
2293 Expr::TypeExpr(dt) => self.gen_data_type(dt),
2294 Expr::QualifiedWildcard { table } => {
2295 self.write(table);
2296 self.write(".*");
2297 }
2298 Expr::Alias { expr, name } => {
2299 self.gen_expr(expr);
2300 self.write(" ");
2301 self.write_keyword("AS ");
2302 self.write(name);
2303 }
2304 Expr::ArrayIndex { expr, index } => {
2305 self.gen_expr(expr);
2306 self.write("[");
2307 self.gen_expr(index);
2308 self.write("]");
2309 }
2310 Expr::JsonAccess {
2311 expr,
2312 path,
2313 as_text,
2314 } => {
2315 self.gen_expr(expr);
2316 if *as_text {
2317 self.write("->>");
2318 } else {
2319 self.write("->");
2320 }
2321 self.gen_expr(path);
2322 }
2323 Expr::Lambda { params, body } => {
2324 if params.len() == 1 {
2325 self.write(¶ms[0]);
2326 } else {
2327 self.write("(");
2328 self.write(¶ms.join(", "));
2329 self.write(")");
2330 }
2331 self.write(" -> ");
2332 self.gen_expr(body);
2333 }
2334 Expr::TypedFunction { func, filter, over } => {
2335 self.gen_typed_function(func);
2336
2337 if let Some(filter_expr) = filter {
2338 self.write(" ");
2339 self.write_keyword("FILTER (WHERE ");
2340 self.gen_expr(filter_expr);
2341 self.write(")");
2342 }
2343 if let Some(spec) = over {
2344 self.write(" ");
2345 self.write_keyword("OVER ");
2346 if let Some(wref) = &spec.window_ref {
2347 if spec.partition_by.is_empty()
2348 && spec.order_by.is_empty()
2349 && spec.frame.is_none()
2350 {
2351 self.write(wref);
2352 } else {
2353 self.write("(");
2354 self.gen_window_spec(spec);
2355 self.write(")");
2356 }
2357 } else {
2358 self.write("(");
2359 self.gen_window_spec(spec);
2360 self.write(")");
2361 }
2362 }
2363 }
2364 Expr::Commented { expr, comments } => {
2365 for comment in comments {
2366 let normalized = self.normalize_comment(comment);
2367 self.write(&normalized);
2368 self.write(" ");
2369 }
2370 self.gen_expr(expr);
2371 }
2372 }
2373 }
2374
2375 fn gen_window_spec(&mut self, spec: &WindowSpec) {
2376 if let Some(wref) = &spec.window_ref {
2377 self.write(wref);
2378 if !spec.partition_by.is_empty() || !spec.order_by.is_empty() || spec.frame.is_some() {
2379 self.write(" ");
2380 }
2381 }
2382 if !spec.partition_by.is_empty() {
2383 self.write_keyword("PARTITION BY ");
2384 self.gen_expr_list(&spec.partition_by);
2385 }
2386 if !spec.order_by.is_empty() {
2387 if !spec.partition_by.is_empty() {
2388 self.write(" ");
2389 }
2390 self.write_keyword("ORDER BY ");
2391 for (i, item) in spec.order_by.iter().enumerate() {
2392 if i > 0 {
2393 self.write(", ");
2394 }
2395 self.gen_expr(&item.expr);
2396 if !item.ascending {
2397 self.write(" ");
2398 self.write_keyword("DESC");
2399 }
2400 if let Some(nulls_first) = item.nulls_first {
2401 if nulls_first {
2402 self.write(" ");
2403 self.write_keyword("NULLS FIRST");
2404 } else {
2405 self.write(" ");
2406 self.write_keyword("NULLS LAST");
2407 }
2408 }
2409 }
2410 }
2411 if let Some(frame) = &spec.frame {
2412 self.write(" ");
2413 self.gen_window_frame(frame);
2414 }
2415 }
2416
2417 fn gen_window_frame(&mut self, frame: &WindowFrame) {
2418 match frame.kind {
2419 WindowFrameKind::Rows => self.write_keyword("ROWS "),
2420 WindowFrameKind::Range => self.write_keyword("RANGE "),
2421 WindowFrameKind::Groups => self.write_keyword("GROUPS "),
2422 }
2423 if let Some(end) = &frame.end {
2424 self.write_keyword("BETWEEN ");
2425 self.gen_window_frame_bound(&frame.start);
2426 self.write(" ");
2427 self.write_keyword("AND ");
2428 self.gen_window_frame_bound(end);
2429 } else {
2430 self.gen_window_frame_bound(&frame.start);
2431 }
2432 }
2433
2434 fn gen_window_frame_bound(&mut self, bound: &WindowFrameBound) {
2435 match bound {
2436 WindowFrameBound::CurrentRow => self.write_keyword("CURRENT ROW"),
2437 WindowFrameBound::Preceding(None) => self.write_keyword("UNBOUNDED PRECEDING"),
2438 WindowFrameBound::Preceding(Some(n)) => {
2439 self.gen_expr(n);
2440 self.write(" ");
2441 self.write_keyword("PRECEDING");
2442 }
2443 WindowFrameBound::Following(None) => self.write_keyword("UNBOUNDED FOLLOWING"),
2444 WindowFrameBound::Following(Some(n)) => {
2445 self.gen_expr(n);
2446 self.write(" ");
2447 self.write_keyword("FOLLOWING");
2448 }
2449 }
2450 }
2451
2452 fn gen_datetime_field(&mut self, field: &DateTimeField) {
2453 let name = match field {
2454 DateTimeField::Year => "YEAR",
2455 DateTimeField::Quarter => "QUARTER",
2456 DateTimeField::Month => "MONTH",
2457 DateTimeField::Week => "WEEK",
2458 DateTimeField::Day => "DAY",
2459 DateTimeField::DayOfWeek => "DOW",
2460 DateTimeField::DayOfYear => "DOY",
2461 DateTimeField::Hour => "HOUR",
2462 DateTimeField::Minute => "MINUTE",
2463 DateTimeField::Second => "SECOND",
2464 DateTimeField::Millisecond => "MILLISECOND",
2465 DateTimeField::Microsecond => "MICROSECOND",
2466 DateTimeField::Nanosecond => "NANOSECOND",
2467 DateTimeField::Epoch => "EPOCH",
2468 DateTimeField::Timezone => "TIMEZONE",
2469 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
2470 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
2471 };
2472 self.write(name);
2473 }
2474
2475 fn gen_typed_function(&mut self, func: &TypedFunction) {
2477 let dialect = self.dialect;
2478 let is_tsql = matches!(dialect, Some(Dialect::Tsql) | Some(Dialect::Fabric));
2479 let is_mysql = matches!(
2480 dialect,
2481 Some(Dialect::Mysql)
2482 | Some(Dialect::SingleStore)
2483 | Some(Dialect::Doris)
2484 | Some(Dialect::StarRocks)
2485 );
2486 let is_bigquery = matches!(dialect, Some(Dialect::BigQuery));
2487 let is_snowflake = matches!(dialect, Some(Dialect::Snowflake));
2488 let is_oracle = matches!(dialect, Some(Dialect::Oracle));
2489 let is_hive_family = matches!(
2490 dialect,
2491 Some(Dialect::Hive) | Some(Dialect::Spark) | Some(Dialect::Databricks)
2492 );
2493
2494 match func {
2495 TypedFunction::DateAdd {
2497 expr,
2498 interval,
2499 unit,
2500 } => {
2501 if is_tsql || is_snowflake {
2502 self.write_keyword("DATEADD(");
2503 if let Some(u) = unit {
2504 self.gen_datetime_field(u);
2505 } else {
2506 self.write_keyword("DAY");
2507 }
2508 self.write(", ");
2509 self.gen_expr(interval);
2510 self.write(", ");
2511 self.gen_expr(expr);
2512 self.write(")");
2513 } else if is_bigquery {
2514 self.write_keyword("DATE_ADD(");
2515 self.gen_expr(expr);
2516 self.write(", ");
2517 self.write_keyword("INTERVAL ");
2518 self.gen_expr(interval);
2519 self.write(" ");
2520 if let Some(u) = unit {
2521 self.gen_datetime_field(u);
2522 } else {
2523 self.write_keyword("DAY");
2524 }
2525 self.write(")");
2526 } else {
2527 self.write_keyword("DATE_ADD(");
2528 self.gen_expr(expr);
2529 self.write(", ");
2530 self.gen_expr(interval);
2531 if let Some(u) = unit {
2532 self.write(", ");
2533 self.gen_datetime_field(u);
2534 }
2535 self.write(")");
2536 }
2537 }
2538 TypedFunction::DateDiff { start, end, unit } => {
2539 if is_tsql || is_snowflake {
2540 self.write_keyword("DATEDIFF(");
2541 if let Some(u) = unit {
2542 self.gen_datetime_field(u);
2543 } else {
2544 self.write_keyword("DAY");
2545 }
2546 self.write(", ");
2547 self.gen_expr(start);
2548 self.write(", ");
2549 self.gen_expr(end);
2550 self.write(")");
2551 } else if is_bigquery {
2552 self.write_keyword("DATE_DIFF(");
2553 self.gen_expr(end);
2554 self.write(", ");
2555 self.gen_expr(start);
2556 self.write(", ");
2557 if let Some(u) = unit {
2558 self.gen_datetime_field(u);
2559 } else {
2560 self.write_keyword("DAY");
2561 }
2562 self.write(")");
2563 } else {
2564 self.write_keyword("DATEDIFF(");
2565 self.gen_expr(start);
2566 self.write(", ");
2567 self.gen_expr(end);
2568 if let Some(u) = unit {
2569 self.write(", ");
2570 self.gen_datetime_field(u);
2571 }
2572 self.write(")");
2573 }
2574 }
2575 TypedFunction::DateTrunc { unit, expr } => {
2576 if is_tsql {
2577 self.write_keyword("DATETRUNC(");
2578 self.gen_datetime_field(unit);
2579 self.write(", ");
2580 self.gen_expr(expr);
2581 self.write(")");
2582 } else if is_oracle {
2583 self.write_keyword("TRUNC(");
2584 self.gen_expr(expr);
2585 self.write(", '");
2586 self.gen_datetime_field(unit);
2587 self.write("')");
2588 } else {
2589 self.write_keyword("DATE_TRUNC(");
2590 self.write("'");
2591 self.gen_datetime_field(unit);
2592 self.write("'");
2593 self.write(", ");
2594 self.gen_expr(expr);
2595 self.write(")");
2596 }
2597 }
2598 TypedFunction::DateSub {
2599 expr,
2600 interval,
2601 unit,
2602 } => {
2603 if is_tsql || is_snowflake {
2604 self.write_keyword("DATEADD(");
2605 if let Some(u) = unit {
2606 self.gen_datetime_field(u);
2607 } else {
2608 self.write_keyword("DAY");
2609 }
2610 self.write(", -(");
2611 self.gen_expr(interval);
2612 self.write("), ");
2613 self.gen_expr(expr);
2614 self.write(")");
2615 } else if is_bigquery {
2616 self.write_keyword("DATE_SUB(");
2617 self.gen_expr(expr);
2618 self.write(", ");
2619 self.write_keyword("INTERVAL ");
2620 self.gen_expr(interval);
2621 self.write(" ");
2622 if let Some(u) = unit {
2623 self.gen_datetime_field(u);
2624 } else {
2625 self.write_keyword("DAY");
2626 }
2627 self.write(")");
2628 } else {
2629 self.write_keyword("DATE_SUB(");
2630 self.gen_expr(expr);
2631 self.write(", ");
2632 self.gen_expr(interval);
2633 if let Some(u) = unit {
2634 self.write(", ");
2635 self.gen_datetime_field(u);
2636 }
2637 self.write(")");
2638 }
2639 }
2640 TypedFunction::CurrentDate => {
2641 if is_tsql {
2642 self.write_keyword("CAST(GETDATE() AS DATE)");
2643 } else if is_mysql || is_hive_family {
2644 self.write_keyword("CURRENT_DATE()");
2645 } else {
2646 self.write_keyword("CURRENT_DATE");
2647 }
2648 }
2649 TypedFunction::CurrentTime => {
2650 if is_tsql {
2651 self.write_keyword("CAST(GETDATE() AS TIME)");
2652 } else if is_mysql || is_hive_family {
2653 self.write_keyword("CURRENT_TIME()");
2654 } else {
2655 self.write_keyword("CURRENT_TIME");
2656 }
2657 }
2658 TypedFunction::CurrentTimestamp => {
2659 if is_tsql {
2660 self.write_keyword("GETDATE()");
2661 } else if is_mysql
2662 || matches!(
2663 dialect,
2664 Some(Dialect::Postgres)
2665 | Some(Dialect::DuckDb)
2666 | Some(Dialect::Sqlite)
2667 | Some(Dialect::Redshift)
2668 )
2669 {
2670 self.write_keyword("NOW()");
2671 } else {
2672 self.write_keyword("CURRENT_TIMESTAMP()");
2673 }
2674 }
2675 TypedFunction::StrToTime { expr, format } => {
2676 if is_mysql {
2677 self.write_keyword("STR_TO_DATE(");
2678 } else if is_bigquery {
2679 self.write_keyword("PARSE_TIMESTAMP(");
2680 } else {
2681 self.write_keyword("TO_TIMESTAMP(");
2682 }
2683 self.gen_expr(expr);
2684 self.write(", ");
2685 self.gen_expr(format);
2686 self.write(")");
2687 }
2688 TypedFunction::TimeToStr { expr, format } => {
2689 if is_mysql || is_hive_family {
2690 self.write_keyword("DATE_FORMAT(");
2691 } else if is_bigquery {
2692 self.write_keyword("FORMAT_TIMESTAMP(");
2693 } else if is_tsql {
2694 self.write_keyword("FORMAT(");
2695 } else {
2696 self.write_keyword("TO_CHAR(");
2697 }
2698 self.gen_expr(expr);
2699 self.write(", ");
2700 self.gen_expr(format);
2701 self.write(")");
2702 }
2703 TypedFunction::TsOrDsToDate { expr } => {
2704 if is_mysql {
2705 self.write_keyword("DATE(");
2706 self.gen_expr(expr);
2707 self.write(")");
2708 } else {
2709 self.write_keyword("CAST(");
2710 self.gen_expr(expr);
2711 self.write(" ");
2712 self.write_keyword("AS DATE)");
2713 }
2714 }
2715 TypedFunction::Year { expr } => {
2716 if is_tsql {
2717 self.write_keyword("YEAR(");
2718 self.gen_expr(expr);
2719 self.write(")");
2720 } else {
2721 self.write_keyword("EXTRACT(YEAR FROM ");
2722 self.gen_expr(expr);
2723 self.write(")");
2724 }
2725 }
2726 TypedFunction::Month { expr } => {
2727 if is_tsql {
2728 self.write_keyword("MONTH(");
2729 self.gen_expr(expr);
2730 self.write(")");
2731 } else {
2732 self.write_keyword("EXTRACT(MONTH FROM ");
2733 self.gen_expr(expr);
2734 self.write(")");
2735 }
2736 }
2737 TypedFunction::Day { expr } => {
2738 if is_tsql {
2739 self.write_keyword("DAY(");
2740 self.gen_expr(expr);
2741 self.write(")");
2742 } else {
2743 self.write_keyword("EXTRACT(DAY FROM ");
2744 self.gen_expr(expr);
2745 self.write(")");
2746 }
2747 }
2748
2749 TypedFunction::Trim {
2751 expr,
2752 trim_type,
2753 trim_chars,
2754 } => {
2755 self.write_keyword("TRIM(");
2756 match trim_type {
2757 TrimType::Leading => self.write_keyword("LEADING "),
2758 TrimType::Trailing => self.write_keyword("TRAILING "),
2759 TrimType::Both => {} }
2761 if let Some(chars) = trim_chars {
2762 self.gen_expr(chars);
2763 self.write(" ");
2764 self.write_keyword("FROM ");
2765 }
2766 self.gen_expr(expr);
2767 self.write(")");
2768 }
2769 TypedFunction::Substring {
2770 expr,
2771 start,
2772 length,
2773 } => {
2774 let name = if is_oracle
2775 || is_hive_family
2776 || is_mysql
2777 || matches!(
2778 dialect,
2779 Some(Dialect::Sqlite)
2780 | Some(Dialect::Doris)
2781 | Some(Dialect::SingleStore)
2782 | Some(Dialect::StarRocks)
2783 ) {
2784 "SUBSTR"
2785 } else {
2786 "SUBSTRING"
2787 };
2788 self.write_keyword(name);
2789 self.write("(");
2790 self.gen_expr(expr);
2791 self.write(", ");
2792 self.gen_expr(start);
2793 if let Some(l) = length {
2794 self.write(", ");
2795 self.gen_expr(l);
2796 }
2797 self.write(")");
2798 }
2799 TypedFunction::Upper { expr } => {
2800 self.write_keyword("UPPER(");
2801 self.gen_expr(expr);
2802 self.write(")");
2803 }
2804 TypedFunction::Lower { expr } => {
2805 self.write_keyword("LOWER(");
2806 self.gen_expr(expr);
2807 self.write(")");
2808 }
2809 TypedFunction::RegexpLike {
2810 expr,
2811 pattern,
2812 flags,
2813 } => {
2814 self.write_keyword("REGEXP_LIKE(");
2815 self.gen_expr(expr);
2816 self.write(", ");
2817 self.gen_expr(pattern);
2818 if let Some(f) = flags {
2819 self.write(", ");
2820 self.gen_expr(f);
2821 }
2822 self.write(")");
2823 }
2824 TypedFunction::RegexpExtract {
2825 expr,
2826 pattern,
2827 group_index,
2828 } => {
2829 if is_bigquery || is_hive_family {
2830 self.write_keyword("REGEXP_EXTRACT(");
2831 } else {
2832 self.write_keyword("REGEXP_SUBSTR(");
2833 }
2834 self.gen_expr(expr);
2835 self.write(", ");
2836 self.gen_expr(pattern);
2837 if let Some(g) = group_index {
2838 self.write(", ");
2839 self.gen_expr(g);
2840 }
2841 self.write(")");
2842 }
2843 TypedFunction::RegexpReplace {
2844 expr,
2845 pattern,
2846 replacement,
2847 flags,
2848 } => {
2849 self.write_keyword("REGEXP_REPLACE(");
2850 self.gen_expr(expr);
2851 self.write(", ");
2852 self.gen_expr(pattern);
2853 self.write(", ");
2854 self.gen_expr(replacement);
2855 if let Some(f) = flags {
2856 self.write(", ");
2857 self.gen_expr(f);
2858 }
2859 self.write(")");
2860 }
2861 TypedFunction::ConcatWs { separator, exprs } => {
2862 self.write_keyword("CONCAT_WS(");
2863 self.gen_expr(separator);
2864 for e in exprs {
2865 self.write(", ");
2866 self.gen_expr(e);
2867 }
2868 self.write(")");
2869 }
2870 TypedFunction::Split { expr, delimiter } => {
2871 if is_tsql {
2872 self.write_keyword("STRING_SPLIT(");
2873 } else {
2874 self.write_keyword("SPLIT(");
2875 }
2876 self.gen_expr(expr);
2877 self.write(", ");
2878 self.gen_expr(delimiter);
2879 self.write(")");
2880 }
2881 TypedFunction::Initcap { expr } => {
2882 self.write_keyword("INITCAP(");
2883 self.gen_expr(expr);
2884 self.write(")");
2885 }
2886 TypedFunction::Length { expr } => {
2887 let name = if is_tsql || is_bigquery || is_snowflake {
2888 "LEN"
2889 } else {
2890 "LENGTH"
2891 };
2892 self.write_keyword(name);
2893 self.write("(");
2894 self.gen_expr(expr);
2895 self.write(")");
2896 }
2897 TypedFunction::Replace { expr, from, to } => {
2898 self.write_keyword("REPLACE(");
2899 self.gen_expr(expr);
2900 self.write(", ");
2901 self.gen_expr(from);
2902 self.write(", ");
2903 self.gen_expr(to);
2904 self.write(")");
2905 }
2906 TypedFunction::Reverse { expr } => {
2907 self.write_keyword("REVERSE(");
2908 self.gen_expr(expr);
2909 self.write(")");
2910 }
2911 TypedFunction::Left { expr, n } => {
2912 self.write_keyword("LEFT(");
2913 self.gen_expr(expr);
2914 self.write(", ");
2915 self.gen_expr(n);
2916 self.write(")");
2917 }
2918 TypedFunction::Right { expr, n } => {
2919 self.write_keyword("RIGHT(");
2920 self.gen_expr(expr);
2921 self.write(", ");
2922 self.gen_expr(n);
2923 self.write(")");
2924 }
2925 TypedFunction::Lpad { expr, length, pad } => {
2926 self.write_keyword("LPAD(");
2927 self.gen_expr(expr);
2928 self.write(", ");
2929 self.gen_expr(length);
2930 if let Some(p) = pad {
2931 self.write(", ");
2932 self.gen_expr(p);
2933 }
2934 self.write(")");
2935 }
2936 TypedFunction::Rpad { expr, length, pad } => {
2937 self.write_keyword("RPAD(");
2938 self.gen_expr(expr);
2939 self.write(", ");
2940 self.gen_expr(length);
2941 if let Some(p) = pad {
2942 self.write(", ");
2943 self.gen_expr(p);
2944 }
2945 self.write(")");
2946 }
2947
2948 TypedFunction::Count { expr, distinct } => {
2950 self.write_keyword("COUNT(");
2951 if *distinct {
2952 self.write_keyword("DISTINCT ");
2953 }
2954 self.gen_expr(expr);
2955 self.write(")");
2956 }
2957 TypedFunction::Sum { expr, distinct } => {
2958 self.write_keyword("SUM(");
2959 if *distinct {
2960 self.write_keyword("DISTINCT ");
2961 }
2962 self.gen_expr(expr);
2963 self.write(")");
2964 }
2965 TypedFunction::Avg { expr, distinct } => {
2966 self.write_keyword("AVG(");
2967 if *distinct {
2968 self.write_keyword("DISTINCT ");
2969 }
2970 self.gen_expr(expr);
2971 self.write(")");
2972 }
2973 TypedFunction::Min { expr } => {
2974 self.write_keyword("MIN(");
2975 self.gen_expr(expr);
2976 self.write(")");
2977 }
2978 TypedFunction::Max { expr } => {
2979 self.write_keyword("MAX(");
2980 self.gen_expr(expr);
2981 self.write(")");
2982 }
2983 TypedFunction::ArrayAgg { expr, distinct } => {
2984 let name = if matches!(dialect, Some(Dialect::DuckDb)) {
2985 "LIST"
2986 } else if is_hive_family {
2987 "COLLECT_LIST"
2988 } else {
2989 "ARRAY_AGG"
2990 };
2991 self.write_keyword(name);
2992 self.write("(");
2993 if *distinct {
2994 self.write_keyword("DISTINCT ");
2995 }
2996 self.gen_expr(expr);
2997 self.write(")");
2998 }
2999 TypedFunction::ApproxDistinct { expr } => {
3000 let name = if is_hive_family
3001 || matches!(
3002 dialect,
3003 Some(Dialect::Presto) | Some(Dialect::Trino) | Some(Dialect::Athena)
3004 ) {
3005 "APPROX_DISTINCT"
3006 } else {
3007 "APPROX_COUNT_DISTINCT"
3008 };
3009 self.write_keyword(name);
3010 self.write("(");
3011 self.gen_expr(expr);
3012 self.write(")");
3013 }
3014 TypedFunction::Variance { expr } => {
3015 let name = if is_tsql || is_oracle {
3016 "VAR"
3017 } else {
3018 "VARIANCE"
3019 };
3020 self.write_keyword(name);
3021 self.write("(");
3022 self.gen_expr(expr);
3023 self.write(")");
3024 }
3025 TypedFunction::VariancePop { expr } => {
3026 let name = if is_tsql { "VARP" } else { "VAR_POP" };
3028 self.write_keyword(name);
3029 self.write("(");
3030 self.gen_expr(expr);
3031 self.write(")");
3032 }
3033 TypedFunction::Stddev { expr } => {
3034 let name = if is_tsql { "STDEV" } else { "STDDEV" };
3037 self.write_keyword(name);
3038 self.write("(");
3039 self.gen_expr(expr);
3040 self.write(")");
3041 }
3042 TypedFunction::StddevPop { expr } => {
3043 let name = if is_tsql { "STDEVP" } else { "STDDEV_POP" };
3046 self.write_keyword(name);
3047 self.write("(");
3048 self.gen_expr(expr);
3049 self.write(")");
3050 }
3051 TypedFunction::GroupConcat {
3052 exprs,
3053 separator,
3054 order_by,
3055 distinct,
3056 } => {
3057 self.gen_group_concat(exprs, separator.as_deref(), order_by, *distinct);
3058 }
3059
3060 TypedFunction::ArrayConcat { arrays } => {
3062 let name = if matches!(
3063 dialect,
3064 Some(Dialect::Postgres) | Some(Dialect::Redshift) | Some(Dialect::DuckDb)
3065 ) {
3066 "ARRAY_CAT"
3067 } else {
3068 "ARRAY_CONCAT"
3069 };
3070 self.write_keyword(name);
3071 self.write("(");
3072 self.gen_expr_list(arrays);
3073 self.write(")");
3074 }
3075 TypedFunction::ArrayContains { array, element } => {
3076 self.write_keyword("ARRAY_CONTAINS(");
3077 self.gen_expr(array);
3078 self.write(", ");
3079 self.gen_expr(element);
3080 self.write(")");
3081 }
3082 TypedFunction::ArraySize { expr } => {
3083 let name = if matches!(dialect, Some(Dialect::Postgres) | Some(Dialect::Redshift)) {
3084 "ARRAY_LENGTH"
3085 } else if is_hive_family {
3086 "SIZE"
3087 } else {
3088 "ARRAY_SIZE"
3089 };
3090 self.write_keyword(name);
3091 self.write("(");
3092 self.gen_expr(expr);
3093 self.write(")");
3094 }
3095 TypedFunction::Explode { expr } => {
3096 self.write_keyword("EXPLODE(");
3097 self.gen_expr(expr);
3098 self.write(")");
3099 }
3100 TypedFunction::GenerateSeries { start, stop, step } => {
3101 self.write_keyword("GENERATE_SERIES(");
3102 self.gen_expr(start);
3103 self.write(", ");
3104 self.gen_expr(stop);
3105 if let Some(s) = step {
3106 self.write(", ");
3107 self.gen_expr(s);
3108 }
3109 self.write(")");
3110 }
3111 TypedFunction::Flatten { expr } => {
3112 self.write_keyword("FLATTEN(");
3113 self.gen_expr(expr);
3114 self.write(")");
3115 }
3116
3117 TypedFunction::JSONExtract { expr, path } => {
3119 if is_tsql {
3120 self.write_keyword("JSON_VALUE(");
3121 } else {
3122 self.write_keyword("JSON_EXTRACT(");
3123 }
3124 self.gen_expr(expr);
3125 self.write(", ");
3126 self.gen_expr(path);
3127 self.write(")");
3128 }
3129 TypedFunction::JSONExtractScalar { expr, path } => {
3130 if is_bigquery {
3131 self.write_keyword("JSON_EXTRACT_SCALAR(");
3132 } else if is_tsql {
3133 self.write_keyword("JSON_VALUE(");
3134 } else {
3135 self.write_keyword("JSON_EXTRACT_SCALAR(");
3136 }
3137 self.gen_expr(expr);
3138 self.write(", ");
3139 self.gen_expr(path);
3140 self.write(")");
3141 }
3142 TypedFunction::ParseJSON { expr } => {
3143 if is_snowflake {
3144 self.write_keyword("PARSE_JSON(");
3145 } else if is_bigquery {
3146 self.write_keyword("JSON_PARSE(");
3147 } else {
3148 self.write_keyword("PARSE_JSON(");
3149 }
3150 self.gen_expr(expr);
3151 self.write(")");
3152 }
3153 TypedFunction::JSONFormat { expr } => {
3154 if is_bigquery {
3155 self.write_keyword("TO_JSON_STRING(");
3156 } else {
3157 self.write_keyword("JSON_FORMAT(");
3158 }
3159 self.gen_expr(expr);
3160 self.write(")");
3161 }
3162
3163 TypedFunction::RowNumber => self.write_keyword("ROW_NUMBER()"),
3165 TypedFunction::Rank => self.write_keyword("RANK()"),
3166 TypedFunction::DenseRank => self.write_keyword("DENSE_RANK()"),
3167 TypedFunction::NTile { n } => {
3168 self.write_keyword("NTILE(");
3169 self.gen_expr(n);
3170 self.write(")");
3171 }
3172 TypedFunction::Lead {
3173 expr,
3174 offset,
3175 default,
3176 } => {
3177 self.write_keyword("LEAD(");
3178 self.gen_expr(expr);
3179 if let Some(o) = offset {
3180 self.write(", ");
3181 self.gen_expr(o);
3182 }
3183 if let Some(d) = default {
3184 self.write(", ");
3185 self.gen_expr(d);
3186 }
3187 self.write(")");
3188 }
3189 TypedFunction::Lag {
3190 expr,
3191 offset,
3192 default,
3193 } => {
3194 self.write_keyword("LAG(");
3195 self.gen_expr(expr);
3196 if let Some(o) = offset {
3197 self.write(", ");
3198 self.gen_expr(o);
3199 }
3200 if let Some(d) = default {
3201 self.write(", ");
3202 self.gen_expr(d);
3203 }
3204 self.write(")");
3205 }
3206 TypedFunction::FirstValue { expr } => {
3207 self.write_keyword("FIRST_VALUE(");
3208 self.gen_expr(expr);
3209 self.write(")");
3210 }
3211 TypedFunction::LastValue { expr } => {
3212 self.write_keyword("LAST_VALUE(");
3213 self.gen_expr(expr);
3214 self.write(")");
3215 }
3216
3217 TypedFunction::Abs { expr } => {
3219 self.write_keyword("ABS(");
3220 self.gen_expr(expr);
3221 self.write(")");
3222 }
3223 TypedFunction::Ceil { expr } => {
3224 let name = if is_tsql { "CEILING" } else { "CEIL" };
3225 self.write_keyword(name);
3226 self.write("(");
3227 self.gen_expr(expr);
3228 self.write(")");
3229 }
3230 TypedFunction::Floor { expr } => {
3231 self.write_keyword("FLOOR(");
3232 self.gen_expr(expr);
3233 self.write(")");
3234 }
3235 TypedFunction::Round { expr, decimals } => {
3236 self.write_keyword("ROUND(");
3237 self.gen_expr(expr);
3238 if let Some(d) = decimals {
3239 self.write(", ");
3240 self.gen_expr(d);
3241 }
3242 self.write(")");
3243 }
3244 TypedFunction::Log { expr, base } => {
3245 if let Some(b) = base {
3246 self.write_keyword("LOG(");
3247 if matches!(dialect, Some(Dialect::Postgres) | Some(Dialect::DuckDb)) {
3248 self.gen_expr(b);
3250 self.write(", ");
3251 self.gen_expr(expr);
3252 } else {
3253 self.gen_expr(expr);
3255 self.write(", ");
3256 self.gen_expr(b);
3257 }
3258 self.write(")");
3259 } else {
3260 self.write_keyword("LOG(");
3262 self.gen_expr(expr);
3263 self.write(")");
3264 }
3265 }
3266 TypedFunction::Ln { expr } => {
3267 self.write_keyword("LN(");
3268 self.gen_expr(expr);
3269 self.write(")");
3270 }
3271 TypedFunction::Pow { base, exponent } => {
3272 let name = if is_tsql || is_oracle { "POWER" } else { "POW" };
3273 self.write_keyword(name);
3274 self.write("(");
3275 self.gen_expr(base);
3276 self.write(", ");
3277 self.gen_expr(exponent);
3278 self.write(")");
3279 }
3280 TypedFunction::Sqrt { expr } => {
3281 self.write_keyword("SQRT(");
3282 self.gen_expr(expr);
3283 self.write(")");
3284 }
3285 TypedFunction::Greatest { exprs } => {
3286 self.write_keyword("GREATEST(");
3287 self.gen_expr_list(exprs);
3288 self.write(")");
3289 }
3290 TypedFunction::Least { exprs } => {
3291 self.write_keyword("LEAST(");
3292 self.gen_expr_list(exprs);
3293 self.write(")");
3294 }
3295 TypedFunction::Mod { left, right } => {
3296 self.write_keyword("MOD(");
3297 self.gen_expr(left);
3298 self.write(", ");
3299 self.gen_expr(right);
3300 self.write(")");
3301 }
3302
3303 TypedFunction::Hex { expr } => {
3305 let name = if matches!(
3306 dialect,
3307 Some(Dialect::Presto) | Some(Dialect::Trino) | Some(Dialect::Athena)
3308 ) {
3309 "TO_HEX"
3310 } else {
3311 "HEX"
3312 };
3313 self.write_keyword(name);
3314 self.write("(");
3315 self.gen_expr(expr);
3316 self.write(")");
3317 }
3318 TypedFunction::Unhex { expr } => {
3319 let name = if matches!(
3320 dialect,
3321 Some(Dialect::Presto) | Some(Dialect::Trino) | Some(Dialect::Athena)
3322 ) {
3323 "FROM_HEX"
3324 } else {
3325 "UNHEX"
3326 };
3327 self.write_keyword(name);
3328 self.write("(");
3329 self.gen_expr(expr);
3330 self.write(")");
3331 }
3332 TypedFunction::Md5 { expr } => {
3333 self.write_keyword("MD5(");
3334 self.gen_expr(expr);
3335 self.write(")");
3336 }
3337 TypedFunction::Sha { expr } => {
3338 let name = if is_mysql { "SHA1" } else { "SHA" };
3339 self.write_keyword(name);
3340 self.write("(");
3341 self.gen_expr(expr);
3342 self.write(")");
3343 }
3344 TypedFunction::Sha2 { expr, bit_length } => {
3345 self.write_keyword("SHA2(");
3346 self.gen_expr(expr);
3347 self.write(", ");
3348 self.gen_expr(bit_length);
3349 self.write(")");
3350 }
3351 }
3352 }
3353
3354 fn gen_group_concat(
3357 &mut self,
3358 exprs: &[Expr],
3359 separator: Option<&Expr>,
3360 order_by: &[OrderByItem],
3361 distinct: bool,
3362 ) {
3363 let dialect = self.dialect;
3364 let is_sqlite = matches!(dialect, Some(Dialect::Sqlite));
3365 let is_string_agg = matches!(
3366 dialect,
3367 Some(Dialect::Postgres)
3368 | Some(Dialect::Redshift)
3369 | Some(Dialect::BigQuery)
3370 | Some(Dialect::Tsql)
3371 | Some(Dialect::Fabric)
3372 | Some(Dialect::DuckDb)
3373 );
3374 let is_listagg = matches!(dialect, Some(Dialect::Oracle) | Some(Dialect::Snowflake));
3375
3376 if is_string_agg {
3377 self.write_keyword("STRING_AGG(");
3379 if distinct {
3380 self.write_keyword("DISTINCT ");
3381 }
3382 self.gen_group_concat_exprs(exprs);
3383 self.write(", ");
3384 match separator {
3385 Some(s) => self.gen_expr(s),
3386 None => self.write("','"),
3387 }
3388 if !order_by.is_empty() {
3389 self.write(" ");
3390 self.gen_group_concat_order_by(order_by);
3391 }
3392 self.write(")");
3393 } else if is_listagg {
3394 self.write_keyword("LISTAGG(");
3396 if distinct {
3397 self.write_keyword("DISTINCT ");
3398 }
3399 self.gen_group_concat_exprs(exprs);
3400 self.write(", ");
3401 match separator {
3402 Some(s) => self.gen_expr(s),
3403 None => self.write("','"),
3404 }
3405 self.write(")");
3406 if !order_by.is_empty() {
3407 self.write(" ");
3408 self.write_keyword("WITHIN GROUP");
3409 self.write(" (");
3410 self.gen_group_concat_order_by(order_by);
3411 self.write(")");
3412 }
3413 } else if is_sqlite {
3414 self.write_keyword("GROUP_CONCAT(");
3417 self.gen_group_concat_exprs(exprs);
3418 if let Some(s) = separator {
3419 self.write(", ");
3420 self.gen_expr(s);
3421 }
3422 self.write(")");
3423 } else {
3424 self.write_keyword("GROUP_CONCAT(");
3426 if distinct {
3427 self.write_keyword("DISTINCT ");
3428 }
3429 self.gen_group_concat_exprs(exprs);
3430 if !order_by.is_empty() {
3431 self.write(" ");
3432 self.gen_group_concat_order_by(order_by);
3433 }
3434 if let Some(s) = separator {
3435 self.write(" ");
3436 self.write_keyword("SEPARATOR");
3437 self.write(" ");
3438 self.gen_expr(s);
3439 }
3440 self.write(")");
3441 }
3442 }
3443
3444 fn gen_group_concat_exprs(&mut self, exprs: &[Expr]) {
3445 for (i, e) in exprs.iter().enumerate() {
3446 if i > 0 {
3447 self.write(", ");
3448 }
3449 self.gen_expr(e);
3450 }
3451 }
3452
3453 fn gen_group_concat_order_by(&mut self, order_by: &[OrderByItem]) {
3454 self.write_keyword("ORDER BY");
3455 self.write(" ");
3456 for (i, item) in order_by.iter().enumerate() {
3457 if i > 0 {
3458 self.write(", ");
3459 }
3460 self.gen_expr(&item.expr);
3461 if !item.ascending {
3462 self.write(" ");
3463 self.write_keyword("DESC");
3464 }
3465 if let Some(nulls_first) = item.nulls_first {
3466 self.write(" ");
3467 self.write_keyword(if nulls_first {
3468 "NULLS FIRST"
3469 } else {
3470 "NULLS LAST"
3471 });
3472 }
3473 }
3474 }
3475}
3476
3477impl Default for Generator {
3478 fn default() -> Self {
3479 Self::new()
3480 }
3481}
3482
3483#[cfg(test)]
3484mod tests {
3485 use super::*;
3486 use crate::parser::Parser;
3487
3488 fn roundtrip(sql: &str) -> String {
3489 let stmt = Parser::new(sql).unwrap().parse_statement().unwrap();
3490 let mut g = Generator::new();
3491 g.generate(&stmt)
3492 }
3493
3494 #[test]
3495 fn test_select_roundtrip() {
3496 assert_eq!(roundtrip("SELECT a, b FROM t"), "SELECT a, b FROM t");
3497 }
3498
3499 #[test]
3500 fn test_select_where() {
3501 assert_eq!(
3502 roundtrip("SELECT x FROM t WHERE x > 10"),
3503 "SELECT x FROM t WHERE x > 10"
3504 );
3505 }
3506
3507 #[test]
3508 fn test_select_wildcard() {
3509 assert_eq!(roundtrip("SELECT * FROM users"), "SELECT * FROM users");
3510 }
3511
3512 #[test]
3513 fn test_insert_values() {
3514 assert_eq!(
3515 roundtrip("INSERT INTO t (a, b) VALUES (1, 'hello')"),
3516 "INSERT INTO t (a, b) VALUES (1, 'hello')"
3517 );
3518 }
3519
3520 #[test]
3521 fn test_delete() {
3522 assert_eq!(
3523 roundtrip("DELETE FROM users WHERE id = 1"),
3524 "DELETE FROM users WHERE id = 1"
3525 );
3526 }
3527
3528 #[test]
3529 fn test_join() {
3530 assert_eq!(
3531 roundtrip("SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"),
3532 "SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"
3533 );
3534 }
3535
3536 #[test]
3537 fn test_create_table() {
3538 assert_eq!(
3539 roundtrip("CREATE TABLE users (id INT NOT NULL, name VARCHAR(255), email TEXT)"),
3540 "CREATE TABLE users (id INT NOT NULL, name VARCHAR(255), email TEXT)"
3541 );
3542 }
3543
3544 #[test]
3545 fn test_cte_roundtrip() {
3546 let sql = "WITH cte AS (SELECT 1 AS x) SELECT x FROM cte";
3547 assert_eq!(
3548 roundtrip(sql),
3549 "WITH cte AS (SELECT 1 AS x) SELECT x FROM cte"
3550 );
3551 }
3552
3553 #[test]
3554 fn test_union_roundtrip() {
3555 let sql = "SELECT 1 UNION ALL SELECT 2";
3556 assert_eq!(roundtrip(sql), "SELECT 1 UNION ALL SELECT 2");
3557 }
3558
3559 #[test]
3560 fn test_cast_roundtrip() {
3561 assert_eq!(
3562 roundtrip("SELECT CAST(x AS INT) FROM t"),
3563 "SELECT CAST(x AS INT) FROM t"
3564 );
3565 }
3566
3567 #[test]
3568 fn test_exists_roundtrip() {
3569 assert_eq!(
3570 roundtrip("SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t2)"),
3571 "SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t2)"
3572 );
3573 }
3574
3575 #[test]
3576 fn test_extract_roundtrip() {
3577 assert_eq!(
3578 roundtrip("SELECT EXTRACT(YEAR FROM created_at) FROM t"),
3579 "SELECT EXTRACT(YEAR FROM created_at) FROM t"
3580 );
3581 }
3582
3583 #[test]
3584 fn test_window_function_roundtrip() {
3585 assert_eq!(
3586 roundtrip("SELECT ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) FROM emp"),
3587 "SELECT ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) FROM emp"
3588 );
3589 }
3590
3591 #[test]
3592 fn test_subquery_from_roundtrip() {
3593 assert_eq!(
3594 roundtrip("SELECT * FROM (SELECT 1 AS x) AS sub"),
3595 "SELECT * FROM (SELECT 1 AS x) AS sub"
3596 );
3597 }
3598
3599 #[test]
3600 fn test_in_subquery_roundtrip() {
3601 assert_eq!(
3602 roundtrip("SELECT * FROM t WHERE id IN (SELECT id FROM t2)"),
3603 "SELECT * FROM t WHERE id IN (SELECT id FROM t2)"
3604 );
3605 }
3606
3607 fn pretty_print(sql: &str) -> String {
3612 let stmt = Parser::new(sql).unwrap().parse_statement().unwrap();
3613 let mut g = Generator::pretty();
3614 g.generate(&stmt)
3615 }
3616
3617 #[test]
3618 fn test_pretty_simple_select() {
3619 assert_eq!(
3620 pretty_print("SELECT a, b, c FROM t"),
3621 "SELECT\n a,\n b,\n c\nFROM\n t"
3622 );
3623 }
3624
3625 #[test]
3626 fn test_pretty_select_where() {
3627 assert_eq!(
3628 pretty_print("SELECT a FROM t WHERE a > 1"),
3629 "SELECT\n a\nFROM\n t\nWHERE\n a > 1"
3630 );
3631 }
3632
3633 #[test]
3634 fn test_pretty_select_group_by_having() {
3635 assert_eq!(
3636 pretty_print("SELECT a, COUNT(*) FROM t GROUP BY a HAVING COUNT(*) > 1"),
3637 "SELECT\n a,\n COUNT(*)\nFROM\n t\nGROUP BY\n a\nHAVING\n COUNT(*) > 1"
3638 );
3639 }
3640
3641 #[test]
3642 fn test_pretty_select_order_by_limit() {
3643 assert_eq!(
3644 pretty_print("SELECT a FROM t ORDER BY a DESC LIMIT 10"),
3645 "SELECT\n a\nFROM\n t\nORDER BY\n a DESC\nLIMIT 10"
3646 );
3647 }
3648
3649 #[test]
3650 fn test_pretty_join() {
3651 assert_eq!(
3652 pretty_print("SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"),
3653 "SELECT\n a.id,\n b.name\nFROM\n a\nINNER JOIN\n b\n ON a.id = b.a_id"
3654 );
3655 }
3656
3657 #[test]
3658 fn test_pretty_cte() {
3659 assert_eq!(
3660 pretty_print("WITH cte AS (SELECT 1 AS x) SELECT x FROM cte"),
3661 "WITH cte AS (\n SELECT\n 1 AS x\n)\nSELECT\n x\nFROM\n cte"
3662 );
3663 }
3664
3665 #[test]
3666 fn test_pretty_union() {
3667 assert_eq!(
3668 pretty_print("SELECT 1 UNION ALL SELECT 2"),
3669 "SELECT\n 1\nUNION ALL\nSELECT\n 2"
3670 );
3671 }
3672
3673 #[test]
3674 fn test_pretty_insert() {
3675 assert_eq!(
3676 pretty_print("INSERT INTO t (a, b) VALUES (1, 'hello'), (2, 'world')"),
3677 "INSERT INTO t (a, b)\nVALUES\n (1, 'hello'),\n (2, 'world')"
3678 );
3679 }
3680
3681 #[test]
3682 fn test_pretty_update() {
3683 assert_eq!(
3684 pretty_print("UPDATE t SET a = 1, b = 2 WHERE c = 3"),
3685 "UPDATE t\nSET\n a = 1,\n b = 2\nWHERE\n c = 3"
3686 );
3687 }
3688
3689 #[test]
3690 fn test_pretty_delete() {
3691 assert_eq!(
3692 pretty_print("DELETE FROM t WHERE id = 1"),
3693 "DELETE FROM t\nWHERE\n id = 1"
3694 );
3695 }
3696
3697 #[test]
3698 fn test_pretty_create_table() {
3699 assert_eq!(
3700 pretty_print("CREATE TABLE t (id INT NOT NULL, name VARCHAR(255), email TEXT)"),
3701 "CREATE TABLE t (\n id INT NOT NULL,\n name VARCHAR(255),\n email TEXT\n)"
3702 );
3703 }
3704
3705 #[test]
3706 fn test_pretty_complex_query() {
3707 let sql = "SELECT a, SUM(b) FROM t1 INNER JOIN t2 ON t1.id = t2.id WHERE t1.x > 1 GROUP BY a HAVING SUM(b) > 10 ORDER BY a LIMIT 100";
3708 let expected = "SELECT\n a,\n SUM(b)\nFROM\n t1\nINNER JOIN\n t2\n ON t1.id = t2.id\nWHERE\n t1.x > 1\nGROUP BY\n a\nHAVING\n SUM(b) > 10\nORDER BY\n a\nLIMIT 100";
3709 assert_eq!(pretty_print(sql), expected);
3710 }
3711
3712 #[test]
3713 fn test_pretty_select_distinct() {
3714 assert_eq!(
3715 pretty_print("SELECT DISTINCT a, b FROM t"),
3716 "SELECT DISTINCT\n a,\n b\nFROM\n t"
3717 );
3718 }
3719}