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