Skip to main content

sqlglot_rust/generator/
sql_generator.rs

1use crate::ast::*;
2
3/// SQL code generator that converts an AST into a SQL string.
4///
5/// Supports all statement and expression types defined in the AST,
6/// including CTEs, subqueries, UNION/INTERSECT/EXCEPT, CAST, window
7/// functions, EXISTS, EXTRACT, INTERVAL, and more.
8pub struct Generator {
9    output: String,
10    /// When true, emit formatted SQL with indentation and newlines.
11    pretty: bool,
12    indent: usize,
13}
14
15impl Generator {
16    #[must_use]
17    pub fn new() -> Self {
18        Self {
19            output: String::new(),
20            pretty: false,
21            indent: 0,
22        }
23    }
24
25    /// Create a generator that produces formatted SQL.
26    #[must_use]
27    pub fn pretty() -> Self {
28        Self {
29            output: String::new(),
30            pretty: true,
31            indent: 0,
32        }
33    }
34
35    /// Generate SQL from a statement.
36    #[must_use]
37    pub fn generate(&mut self, statement: &Statement) -> String {
38        self.output.clear();
39        self.gen_statement(statement);
40        self.output.clone()
41    }
42
43    /// Generate SQL for an expression (static helper for `Expr::sql()`).
44    #[must_use]
45    pub fn expr_to_sql(expr: &Expr) -> String {
46        let mut g = Self::new();
47        g.gen_expr(expr);
48        g.output
49    }
50
51    fn write(&mut self, s: &str) {
52        self.output.push_str(s);
53    }
54
55    /// Emit a newline followed by current indentation (pretty mode only).
56    fn newline(&mut self) {
57        if self.pretty {
58            self.output.push('\n');
59            for _ in 0..self.indent {
60                self.output.push_str("  ");
61            }
62        }
63    }
64
65    /// In pretty mode: newline + indent. In compact mode: a single space.
66    fn sep(&mut self) {
67        if self.pretty {
68            self.newline();
69        } else {
70            self.output.push(' ');
71        }
72    }
73
74    fn indent_up(&mut self) {
75        self.indent += 1;
76    }
77
78    fn indent_down(&mut self) {
79        self.indent = self.indent.saturating_sub(1);
80    }
81
82    fn write_keyword(&mut self, s: &str) {
83        self.write(s);
84    }
85
86    /// Write an identifier with the given quoting style.
87    fn write_quoted(&mut self, name: &str, style: QuoteStyle) {
88        match style {
89            QuoteStyle::None => self.write(name),
90            QuoteStyle::DoubleQuote => {
91                self.write("\"");
92                self.write(&name.replace('"', "\"\""));
93                self.write("\"");
94            }
95            QuoteStyle::Backtick => {
96                self.write("`");
97                self.write(&name.replace('`', "``"));
98                self.write("`");
99            }
100            QuoteStyle::Bracket => {
101                self.write("[");
102                self.write(&name.replace(']', "]]"));
103                self.write("]");
104            }
105        }
106    }
107
108    // ══════════════════════════════════════════════════════════════
109    // Statements
110    // ══════════════════════════════════════════════════════════════
111
112    fn gen_statement(&mut self, statement: &Statement) {
113        match statement {
114            Statement::Select(s) => self.gen_select(s),
115            Statement::Insert(s) => self.gen_insert(s),
116            Statement::Update(s) => self.gen_update(s),
117            Statement::Delete(s) => self.gen_delete(s),
118            Statement::CreateTable(s) => self.gen_create_table(s),
119            Statement::DropTable(s) => self.gen_drop_table(s),
120            Statement::SetOperation(s) => self.gen_set_operation(s),
121            Statement::AlterTable(s) => self.gen_alter_table(s),
122            Statement::CreateView(s) => self.gen_create_view(s),
123            Statement::DropView(s) => self.gen_drop_view(s),
124            Statement::Truncate(s) => self.gen_truncate(s),
125            Statement::Transaction(s) => self.gen_transaction(s),
126            Statement::Explain(s) => self.gen_explain(s),
127            Statement::Use(s) => self.gen_use(s),
128            Statement::Expression(e) => self.gen_expr(e),
129        }
130    }
131
132    // ── SELECT ──────────────────────────────────────────────────
133
134    fn gen_select(&mut self, sel: &SelectStatement) {
135        // CTEs
136        if !sel.ctes.is_empty() {
137            self.gen_ctes(&sel.ctes);
138            self.sep();
139        }
140
141        self.write_keyword("SELECT");
142        if sel.distinct {
143            self.write(" ");
144            self.write_keyword("DISTINCT");
145        }
146        if let Some(top) = &sel.top {
147            self.write(" ");
148            self.write_keyword("TOP ");
149            self.gen_expr(top);
150        }
151
152        // columns
153        if self.pretty {
154            self.indent_up();
155            for (i, item) in sel.columns.iter().enumerate() {
156                self.newline();
157                self.gen_select_item(item);
158                if i < sel.columns.len() - 1 {
159                    self.write(",");
160                }
161            }
162            self.indent_down();
163        } else {
164            self.write(" ");
165            for (i, item) in sel.columns.iter().enumerate() {
166                if i > 0 {
167                    self.write(", ");
168                }
169                self.gen_select_item(item);
170            }
171        }
172
173        if let Some(from) = &sel.from {
174            self.sep();
175            self.write_keyword("FROM");
176            if self.pretty {
177                self.indent_up();
178                self.newline();
179                self.gen_table_source(&from.source);
180                self.indent_down();
181            } else {
182                self.write(" ");
183                self.gen_table_source(&from.source);
184            }
185        }
186
187        for join in &sel.joins {
188            self.gen_join(join);
189        }
190
191        if let Some(wh) = &sel.where_clause {
192            self.sep();
193            self.write_keyword("WHERE");
194            if self.pretty {
195                self.indent_up();
196                self.newline();
197                self.gen_expr(wh);
198                self.indent_down();
199            } else {
200                self.write(" ");
201                self.gen_expr(wh);
202            }
203        }
204
205        if !sel.group_by.is_empty() {
206            self.sep();
207            self.write_keyword("GROUP BY");
208            if self.pretty {
209                self.indent_up();
210                self.newline();
211                self.gen_expr_list(&sel.group_by);
212                self.indent_down();
213            } else {
214                self.write(" ");
215                self.gen_expr_list(&sel.group_by);
216            }
217        }
218
219        if let Some(having) = &sel.having {
220            self.sep();
221            self.write_keyword("HAVING");
222            if self.pretty {
223                self.indent_up();
224                self.newline();
225                self.gen_expr(having);
226                self.indent_down();
227            } else {
228                self.write(" ");
229                self.gen_expr(having);
230            }
231        }
232
233        if let Some(qualify) = &sel.qualify {
234            self.sep();
235            self.write_keyword("QUALIFY");
236            if self.pretty {
237                self.indent_up();
238                self.newline();
239                self.gen_expr(qualify);
240                self.indent_down();
241            } else {
242                self.write(" ");
243                self.gen_expr(qualify);
244            }
245        }
246
247        if !sel.window_definitions.is_empty() {
248            self.sep();
249            self.write_keyword("WINDOW ");
250            for (i, wd) in sel.window_definitions.iter().enumerate() {
251                if i > 0 {
252                    self.write(", ");
253                }
254                self.write(&wd.name);
255                self.write(" AS (");
256                self.gen_window_spec(&wd.spec);
257                self.write(")");
258            }
259        }
260
261        self.gen_order_by(&sel.order_by);
262
263        if let Some(limit) = &sel.limit {
264            self.sep();
265            self.write_keyword("LIMIT ");
266            self.gen_expr(limit);
267        }
268
269        if let Some(offset) = &sel.offset {
270            self.sep();
271            self.write_keyword("OFFSET ");
272            self.gen_expr(offset);
273        }
274
275        if let Some(fetch) = &sel.fetch_first {
276            self.sep();
277            self.write_keyword("FETCH FIRST ");
278            self.gen_expr(fetch);
279            self.write(" ");
280            self.write_keyword("ROWS ONLY");
281        }
282    }
283
284    fn gen_ctes(&mut self, ctes: &[Cte]) {
285        self.write_keyword("WITH ");
286        if ctes.iter().any(|c| c.recursive) {
287            self.write_keyword("RECURSIVE ");
288        }
289        for (i, cte) in ctes.iter().enumerate() {
290            if i > 0 {
291                self.write(",");
292                self.sep();
293            }
294            self.write(&cte.name);
295            if !cte.columns.is_empty() {
296                self.write("(");
297                self.write(&cte.columns.join(", "));
298                self.write(")");
299            }
300            self.write(" ");
301            self.write_keyword("AS ");
302            if let Some(true) = cte.materialized {
303                self.write_keyword("MATERIALIZED ");
304            } else if let Some(false) = cte.materialized {
305                self.write_keyword("NOT MATERIALIZED ");
306            }
307            self.write("(");
308            if self.pretty {
309                self.indent_up();
310                self.newline();
311                self.gen_statement(&cte.query);
312                self.indent_down();
313                self.newline();
314            } else {
315                self.gen_statement(&cte.query);
316            }
317            self.write(")");
318        }
319    }
320
321    fn gen_select_item(&mut self, item: &SelectItem) {
322        match item {
323            SelectItem::Wildcard => self.write("*"),
324            SelectItem::QualifiedWildcard { table } => {
325                self.write(table);
326                self.write(".*");
327            }
328            SelectItem::Expr { expr, alias } => {
329                self.gen_expr(expr);
330                if let Some(alias) = alias {
331                    self.write(" ");
332                    self.write_keyword("AS ");
333                    self.write(alias);
334                }
335            }
336        }
337    }
338
339    fn gen_table_source(&mut self, source: &TableSource) {
340        match source {
341            TableSource::Table(table_ref) => self.gen_table_ref(table_ref),
342            TableSource::Subquery { query, alias } => {
343                self.write("(");
344                self.gen_statement(query);
345                self.write(")");
346                if let Some(alias) = alias {
347                    self.write(" ");
348                    self.write_keyword("AS ");
349                    self.write(alias);
350                }
351            }
352            TableSource::TableFunction { name, args, alias } => {
353                self.write(name);
354                self.write("(");
355                self.gen_expr_list(args);
356                self.write(")");
357                if let Some(alias) = alias {
358                    self.write(" ");
359                    self.write_keyword("AS ");
360                    self.write(alias);
361                }
362            }
363            TableSource::Lateral { source } => {
364                self.write_keyword("LATERAL ");
365                self.gen_table_source(source);
366            }
367            TableSource::Unnest { expr, alias, with_offset } => {
368                self.write_keyword("UNNEST(");
369                self.gen_expr(expr);
370                self.write(")");
371                if let Some(alias) = alias {
372                    self.write(" ");
373                    self.write_keyword("AS ");
374                    self.write(alias);
375                }
376                if *with_offset {
377                    self.write(" ");
378                    self.write_keyword("WITH OFFSET");
379                }
380            }
381        }
382    }
383
384    fn gen_table_ref(&mut self, table: &TableRef) {
385        if let Some(catalog) = &table.catalog {
386            self.write(catalog);
387            self.write(".");
388        }
389        if let Some(schema) = &table.schema {
390            self.write(schema);
391            self.write(".");
392        }
393        self.write_quoted(&table.name, table.name_quote_style);
394        if let Some(alias) = &table.alias {
395            self.write(" ");
396            self.write_keyword("AS ");
397            self.write(alias);
398        }
399    }
400
401    fn gen_join(&mut self, join: &JoinClause) {
402        let join_kw = match join.join_type {
403            JoinType::Inner => "INNER JOIN",
404            JoinType::Left => "LEFT JOIN",
405            JoinType::Right => "RIGHT JOIN",
406            JoinType::Full => "FULL JOIN",
407            JoinType::Cross => "CROSS JOIN",
408            JoinType::Natural => "NATURAL JOIN",
409            JoinType::Lateral => "LATERAL JOIN",
410        };
411        self.sep();
412        self.write_keyword(join_kw);
413        if self.pretty {
414            self.indent_up();
415            self.newline();
416            self.gen_table_source(&join.table);
417        } else {
418            self.write(" ");
419            self.gen_table_source(&join.table);
420        }
421        if let Some(on) = &join.on {
422            if self.pretty {
423                self.newline();
424            } else {
425                self.write(" ");
426            }
427            self.write_keyword("ON ");
428            self.gen_expr(on);
429        }
430        if !join.using.is_empty() {
431            if self.pretty {
432                self.newline();
433            } else {
434                self.write(" ");
435            }
436            self.write_keyword("USING (");
437            self.write(&join.using.join(", "));
438            self.write(")");
439        }
440        if self.pretty {
441            self.indent_down();
442        }
443    }
444
445    fn gen_order_by(&mut self, items: &[OrderByItem]) {
446        if items.is_empty() {
447            return;
448        }
449        self.sep();
450        self.write_keyword("ORDER BY");
451        if self.pretty {
452            self.indent_up();
453            self.newline();
454        } else {
455            self.write(" ");
456        }
457        for (i, item) in items.iter().enumerate() {
458            if i > 0 {
459                self.write(", ");
460            }
461            self.gen_expr(&item.expr);
462            if !item.ascending {
463                self.write(" ");
464                self.write_keyword("DESC");
465            }
466            if let Some(nulls_first) = item.nulls_first {
467                if nulls_first {
468                    self.write(" ");
469                    self.write_keyword("NULLS FIRST");
470                } else {
471                    self.write(" ");
472                    self.write_keyword("NULLS LAST");
473                }
474            }
475        }
476        if self.pretty {
477            self.indent_down();
478        }
479    }
480
481    // ── Set operations ──────────────────────────────────────────
482
483    fn gen_set_operation(&mut self, sop: &SetOperationStatement) {
484        self.gen_statement(&sop.left);
485        let op_kw = match sop.op {
486            SetOperationType::Union => "UNION",
487            SetOperationType::Intersect => "INTERSECT",
488            SetOperationType::Except => "EXCEPT",
489        };
490        self.sep();
491        self.write_keyword(op_kw);
492        if sop.all {
493            self.write(" ");
494            self.write_keyword("ALL");
495        }
496        self.sep();
497        self.gen_statement(&sop.right);
498
499        self.gen_order_by(&sop.order_by);
500
501        if let Some(limit) = &sop.limit {
502            self.sep();
503            self.write_keyword("LIMIT ");
504            self.gen_expr(limit);
505        }
506        if let Some(offset) = &sop.offset {
507            self.sep();
508            self.write_keyword("OFFSET ");
509            self.gen_expr(offset);
510        }
511    }
512
513    // ── INSERT ──────────────────────────────────────────────────
514
515    fn gen_insert(&mut self, ins: &InsertStatement) {
516        self.write_keyword("INSERT INTO ");
517        self.gen_table_ref(&ins.table);
518
519        if !ins.columns.is_empty() {
520            self.write(" (");
521            self.write(&ins.columns.join(", "));
522            self.write(")");
523        }
524
525        match &ins.source {
526            InsertSource::Values(rows) => {
527                self.sep();
528                self.write_keyword("VALUES");
529                if self.pretty {
530                    self.indent_up();
531                    for (i, row) in rows.iter().enumerate() {
532                        self.newline();
533                        self.write("(");
534                        self.gen_expr_list(row);
535                        self.write(")");
536                        if i < rows.len() - 1 {
537                            self.write(",");
538                        }
539                    }
540                    self.indent_down();
541                } else {
542                    self.write(" ");
543                    for (i, row) in rows.iter().enumerate() {
544                        if i > 0 {
545                            self.write(", ");
546                        }
547                        self.write("(");
548                        self.gen_expr_list(row);
549                        self.write(")");
550                    }
551                }
552            }
553            InsertSource::Query(query) => {
554                self.sep();
555                self.gen_statement(query);
556            }
557            InsertSource::Default => {
558                self.sep();
559                self.write_keyword("DEFAULT VALUES");
560            }
561        }
562
563        if let Some(on_conflict) = &ins.on_conflict {
564            self.sep();
565            self.write_keyword("ON CONFLICT");
566            if !on_conflict.columns.is_empty() {
567                self.write(" (");
568                self.write(&on_conflict.columns.join(", "));
569                self.write(")");
570            }
571            match &on_conflict.action {
572                ConflictAction::DoNothing => {
573                    self.write(" ");
574                    self.write_keyword("DO NOTHING");
575                }
576                ConflictAction::DoUpdate(assignments) => {
577                    self.write(" ");
578                    self.write_keyword("DO UPDATE SET ");
579                    for (i, (col, val)) in assignments.iter().enumerate() {
580                        if i > 0 {
581                            self.write(", ");
582                        }
583                        self.write(col);
584                        self.write(" = ");
585                        self.gen_expr(val);
586                    }
587                }
588            }
589        }
590
591        if !ins.returning.is_empty() {
592            self.sep();
593            self.write_keyword("RETURNING ");
594            for (i, item) in ins.returning.iter().enumerate() {
595                if i > 0 {
596                    self.write(", ");
597                }
598                self.gen_select_item(item);
599            }
600        }
601    }
602
603    // ── UPDATE ──────────────────────────────────────────────────
604
605    fn gen_update(&mut self, upd: &UpdateStatement) {
606        self.write_keyword("UPDATE ");
607        self.gen_table_ref(&upd.table);
608        self.sep();
609        self.write_keyword("SET");
610
611        if self.pretty {
612            self.indent_up();
613            for (i, (col, val)) in upd.assignments.iter().enumerate() {
614                self.newline();
615                self.write(col);
616                self.write(" = ");
617                self.gen_expr(val);
618                if i < upd.assignments.len() - 1 {
619                    self.write(",");
620                }
621            }
622            self.indent_down();
623        } else {
624            self.write(" ");
625            for (i, (col, val)) in upd.assignments.iter().enumerate() {
626                if i > 0 {
627                    self.write(", ");
628                }
629                self.write(col);
630                self.write(" = ");
631                self.gen_expr(val);
632            }
633        }
634
635        if let Some(from) = &upd.from {
636            self.sep();
637            self.write_keyword("FROM ");
638            self.gen_table_source(&from.source);
639        }
640
641        if let Some(wh) = &upd.where_clause {
642            self.sep();
643            self.write_keyword("WHERE");
644            if self.pretty {
645                self.indent_up();
646                self.newline();
647                self.gen_expr(wh);
648                self.indent_down();
649            } else {
650                self.write(" ");
651                self.gen_expr(wh);
652            }
653        }
654
655        if !upd.returning.is_empty() {
656            self.sep();
657            self.write_keyword("RETURNING ");
658            for (i, item) in upd.returning.iter().enumerate() {
659                if i > 0 {
660                    self.write(", ");
661                }
662                self.gen_select_item(item);
663            }
664        }
665    }
666
667    // ── DELETE ──────────────────────────────────────────────────
668
669    fn gen_delete(&mut self, del: &DeleteStatement) {
670        self.write_keyword("DELETE FROM ");
671        self.gen_table_ref(&del.table);
672
673        if let Some(using) = &del.using {
674            self.sep();
675            self.write_keyword("USING ");
676            self.gen_table_source(&using.source);
677        }
678
679        if let Some(wh) = &del.where_clause {
680            self.sep();
681            self.write_keyword("WHERE");
682            if self.pretty {
683                self.indent_up();
684                self.newline();
685                self.gen_expr(wh);
686                self.indent_down();
687            } else {
688                self.write(" ");
689                self.gen_expr(wh);
690            }
691        }
692
693        if !del.returning.is_empty() {
694            self.sep();
695            self.write_keyword("RETURNING ");
696            for (i, item) in del.returning.iter().enumerate() {
697                if i > 0 {
698                    self.write(", ");
699                }
700                self.gen_select_item(item);
701            }
702        }
703    }
704
705    // ── CREATE TABLE ────────────────────────────────────────────
706
707    fn gen_create_table(&mut self, ct: &CreateTableStatement) {
708        self.write_keyword("CREATE ");
709        if ct.temporary {
710            self.write_keyword("TEMPORARY ");
711        }
712        self.write_keyword("TABLE ");
713        if ct.if_not_exists {
714            self.write_keyword("IF NOT EXISTS ");
715        }
716        self.gen_table_ref(&ct.table);
717
718        if let Some(as_select) = &ct.as_select {
719            self.write(" ");
720            self.write_keyword("AS ");
721            self.gen_statement(as_select);
722            return;
723        }
724
725        self.write(" (");
726
727        if self.pretty {
728            self.indent_up();
729            for (i, col) in ct.columns.iter().enumerate() {
730                self.newline();
731                self.gen_column_def(col);
732                if i < ct.columns.len() - 1 || !ct.constraints.is_empty() {
733                    self.write(",");
734                }
735            }
736            for (i, constraint) in ct.constraints.iter().enumerate() {
737                self.newline();
738                self.gen_table_constraint(constraint);
739                if i < ct.constraints.len() - 1 {
740                    self.write(",");
741                }
742            }
743            self.indent_down();
744            self.newline();
745        } else {
746            for (i, col) in ct.columns.iter().enumerate() {
747                if i > 0 {
748                    self.write(", ");
749                }
750                self.gen_column_def(col);
751            }
752            for (i, constraint) in ct.constraints.iter().enumerate() {
753                if i + ct.columns.len() > 0 {
754                    self.write(", ");
755                }
756                self.gen_table_constraint(constraint);
757            }
758        }
759
760        self.write(")");
761    }
762
763    fn gen_column_def(&mut self, col: &ColumnDef) {
764        self.write(&col.name);
765        self.write(" ");
766        self.gen_data_type(&col.data_type);
767
768        if col.primary_key {
769            self.write(" ");
770            self.write_keyword("PRIMARY KEY");
771        }
772        if col.unique {
773            self.write(" ");
774            self.write_keyword("UNIQUE");
775        }
776        if col.auto_increment {
777            self.write(" ");
778            self.write_keyword("AUTOINCREMENT");
779        }
780
781        match col.nullable {
782            Some(false) => {
783                self.write(" ");
784                self.write_keyword("NOT NULL");
785            }
786            Some(true) => {
787                self.write(" ");
788                self.write_keyword("NULL");
789            }
790            None => {}
791        }
792
793        if let Some(default) = &col.default {
794            self.write(" ");
795            self.write_keyword("DEFAULT ");
796            self.gen_expr(default);
797        }
798
799        if let Some(collation) = &col.collation {
800            self.write(" ");
801            self.write_keyword("COLLATE ");
802            self.write(collation);
803        }
804
805        if let Some(comment) = &col.comment {
806            self.write(" ");
807            self.write_keyword("COMMENT '");
808            self.write(&comment.replace('\'', "''"));
809            self.write("'");
810        }
811    }
812
813    fn gen_table_constraint(&mut self, constraint: &TableConstraint) {
814        match constraint {
815            TableConstraint::PrimaryKey { name, columns } => {
816                if let Some(name) = name {
817                    self.write_keyword("CONSTRAINT ");
818                    self.write(name);
819                    self.write(" ");
820                }
821                self.write_keyword("PRIMARY KEY (");
822                self.write(&columns.join(", "));
823                self.write(")");
824            }
825            TableConstraint::Unique { name, columns } => {
826                if let Some(name) = name {
827                    self.write_keyword("CONSTRAINT ");
828                    self.write(name);
829                    self.write(" ");
830                }
831                self.write_keyword("UNIQUE (");
832                self.write(&columns.join(", "));
833                self.write(")");
834            }
835            TableConstraint::ForeignKey {
836                name,
837                columns,
838                ref_table,
839                ref_columns,
840                on_delete,
841                on_update,
842            } => {
843                if let Some(name) = name {
844                    self.write_keyword("CONSTRAINT ");
845                    self.write(name);
846                    self.write(" ");
847                }
848                self.write_keyword("FOREIGN KEY (");
849                self.write(&columns.join(", "));
850                self.write(") ");
851                self.write_keyword("REFERENCES ");
852                self.gen_table_ref(ref_table);
853                self.write(" (");
854                self.write(&ref_columns.join(", "));
855                self.write(")");
856                if let Some(action) = on_delete {
857                    self.write(" ");
858                    self.write_keyword("ON DELETE ");
859                    self.gen_referential_action(action);
860                }
861                if let Some(action) = on_update {
862                    self.write(" ");
863                    self.write_keyword("ON UPDATE ");
864                    self.gen_referential_action(action);
865                }
866            }
867            TableConstraint::Check { name, expr } => {
868                if let Some(name) = name {
869                    self.write_keyword("CONSTRAINT ");
870                    self.write(name);
871                    self.write(" ");
872                }
873                self.write_keyword("CHECK (");
874                self.gen_expr(expr);
875                self.write(")");
876            }
877        }
878    }
879
880    fn gen_referential_action(&mut self, action: &ReferentialAction) {
881        match action {
882            ReferentialAction::Cascade => self.write_keyword("CASCADE"),
883            ReferentialAction::Restrict => self.write_keyword("RESTRICT"),
884            ReferentialAction::NoAction => self.write_keyword("NO ACTION"),
885            ReferentialAction::SetNull => self.write_keyword("SET NULL"),
886            ReferentialAction::SetDefault => self.write_keyword("SET DEFAULT"),
887        }
888    }
889
890    // ── DROP TABLE ──────────────────────────────────────────────
891
892    fn gen_drop_table(&mut self, dt: &DropTableStatement) {
893        self.write_keyword("DROP TABLE ");
894        if dt.if_exists {
895            self.write_keyword("IF EXISTS ");
896        }
897        self.gen_table_ref(&dt.table);
898        if dt.cascade {
899            self.write(" ");
900            self.write_keyword("CASCADE");
901        }
902    }
903
904    // ── ALTER TABLE ─────────────────────────────────────────────
905
906    fn gen_alter_table(&mut self, alt: &AlterTableStatement) {
907        self.write_keyword("ALTER TABLE ");
908        self.gen_table_ref(&alt.table);
909
910        for (i, action) in alt.actions.iter().enumerate() {
911            if i > 0 {
912                self.write(",");
913            }
914            self.write(" ");
915            match action {
916                AlterTableAction::AddColumn(col) => {
917                    self.write_keyword("ADD COLUMN ");
918                    self.gen_column_def(col);
919                }
920                AlterTableAction::DropColumn { name, if_exists } => {
921                    self.write_keyword("DROP COLUMN ");
922                    if *if_exists {
923                        self.write_keyword("IF EXISTS ");
924                    }
925                    self.write(name);
926                }
927                AlterTableAction::RenameColumn { old_name, new_name } => {
928                    self.write_keyword("RENAME COLUMN ");
929                    self.write(old_name);
930                    self.write(" ");
931                    self.write_keyword("TO ");
932                    self.write(new_name);
933                }
934                AlterTableAction::AlterColumnType { name, data_type } => {
935                    self.write_keyword("ALTER COLUMN ");
936                    self.write(name);
937                    self.write(" ");
938                    self.write_keyword("TYPE ");
939                    self.gen_data_type(data_type);
940                }
941                AlterTableAction::AddConstraint(constraint) => {
942                    self.write_keyword("ADD ");
943                    self.gen_table_constraint(constraint);
944                }
945                AlterTableAction::DropConstraint { name } => {
946                    self.write_keyword("DROP CONSTRAINT ");
947                    self.write(name);
948                }
949                AlterTableAction::RenameTable { new_name } => {
950                    self.write_keyword("RENAME TO ");
951                    self.write(new_name);
952                }
953            }
954        }
955    }
956
957    // ── CREATE / DROP VIEW ──────────────────────────────────────
958
959    fn gen_create_view(&mut self, cv: &CreateViewStatement) {
960        self.write_keyword("CREATE ");
961        if cv.or_replace {
962            self.write_keyword("OR REPLACE ");
963        }
964        if cv.materialized {
965            self.write_keyword("MATERIALIZED ");
966        }
967        self.write_keyword("VIEW ");
968        if cv.if_not_exists {
969            self.write_keyword("IF NOT EXISTS ");
970        }
971        self.gen_table_ref(&cv.name);
972
973        if !cv.columns.is_empty() {
974            self.write(" (");
975            self.write(&cv.columns.join(", "));
976            self.write(")");
977        }
978
979        self.write(" ");
980        self.write_keyword("AS ");
981        self.gen_statement(&cv.query);
982    }
983
984    fn gen_drop_view(&mut self, dv: &DropViewStatement) {
985        self.write_keyword("DROP ");
986        if dv.materialized {
987            self.write_keyword("MATERIALIZED ");
988        }
989        self.write_keyword("VIEW ");
990        if dv.if_exists {
991            self.write_keyword("IF EXISTS ");
992        }
993        self.gen_table_ref(&dv.name);
994    }
995
996    // ── TRUNCATE ────────────────────────────────────────────────
997
998    fn gen_truncate(&mut self, t: &TruncateStatement) {
999        self.write_keyword("TRUNCATE TABLE ");
1000        self.gen_table_ref(&t.table);
1001    }
1002
1003    // ── Transaction ─────────────────────────────────────────────
1004
1005    fn gen_transaction(&mut self, t: &TransactionStatement) {
1006        match t {
1007            TransactionStatement::Begin => self.write_keyword("BEGIN"),
1008            TransactionStatement::Commit => self.write_keyword("COMMIT"),
1009            TransactionStatement::Rollback => self.write_keyword("ROLLBACK"),
1010            TransactionStatement::Savepoint(name) => {
1011                self.write_keyword("SAVEPOINT ");
1012                self.write(name);
1013            }
1014            TransactionStatement::ReleaseSavepoint(name) => {
1015                self.write_keyword("RELEASE SAVEPOINT ");
1016                self.write(name);
1017            }
1018            TransactionStatement::RollbackTo(name) => {
1019                self.write_keyword("ROLLBACK TO SAVEPOINT ");
1020                self.write(name);
1021            }
1022        }
1023    }
1024
1025    // ── EXPLAIN ─────────────────────────────────────────────────
1026
1027    fn gen_explain(&mut self, e: &ExplainStatement) {
1028        self.write_keyword("EXPLAIN ");
1029        if e.analyze {
1030            self.write_keyword("ANALYZE ");
1031        }
1032        self.gen_statement(&e.statement);
1033    }
1034
1035    // ── USE ─────────────────────────────────────────────────────
1036
1037    fn gen_use(&mut self, u: &UseStatement) {
1038        self.write_keyword("USE ");
1039        self.write(&u.name);
1040    }
1041
1042    // ══════════════════════════════════════════════════════════════
1043    // Data types
1044    // ══════════════════════════════════════════════════════════════
1045
1046    fn gen_data_type(&mut self, dt: &DataType) {
1047        match dt {
1048            DataType::TinyInt => self.write("TINYINT"),
1049            DataType::SmallInt => self.write("SMALLINT"),
1050            DataType::Int => self.write("INT"),
1051            DataType::BigInt => self.write("BIGINT"),
1052            DataType::Float => self.write("FLOAT"),
1053            DataType::Double => self.write("DOUBLE"),
1054            DataType::Real => self.write("REAL"),
1055            DataType::Decimal { precision, scale } | DataType::Numeric { precision, scale } => {
1056                self.write(if matches!(dt, DataType::Numeric { .. }) { "NUMERIC" } else { "DECIMAL" });
1057                if let Some(p) = precision {
1058                    self.write(&format!("({p}"));
1059                    if let Some(s) = scale {
1060                        self.write(&format!(", {s}"));
1061                    }
1062                    self.write(")");
1063                }
1064            }
1065            DataType::Varchar(len) => {
1066                self.write("VARCHAR");
1067                if let Some(n) = len {
1068                    self.write(&format!("({n})"));
1069                }
1070            }
1071            DataType::Char(len) => {
1072                self.write("CHAR");
1073                if let Some(n) = len {
1074                    self.write(&format!("({n})"));
1075                }
1076            }
1077            DataType::Text => self.write("TEXT"),
1078            DataType::String => self.write("STRING"),
1079            DataType::Binary(len) => {
1080                self.write("BINARY");
1081                if let Some(n) = len {
1082                    self.write(&format!("({n})"));
1083                }
1084            }
1085            DataType::Varbinary(len) => {
1086                self.write("VARBINARY");
1087                if let Some(n) = len {
1088                    self.write(&format!("({n})"));
1089                }
1090            }
1091            DataType::Boolean => self.write("BOOLEAN"),
1092            DataType::Date => self.write("DATE"),
1093            DataType::Time { precision } => {
1094                self.write("TIME");
1095                if let Some(p) = precision {
1096                    self.write(&format!("({p})"));
1097                }
1098            }
1099            DataType::Timestamp { precision, with_tz } => {
1100                self.write("TIMESTAMP");
1101                if let Some(p) = precision {
1102                    self.write(&format!("({p})"));
1103                }
1104                if *with_tz {
1105                    self.write(" WITH TIME ZONE");
1106                }
1107            }
1108            DataType::Interval => self.write("INTERVAL"),
1109            DataType::DateTime => self.write("DATETIME"),
1110            DataType::Blob => self.write("BLOB"),
1111            DataType::Bytea => self.write("BYTEA"),
1112            DataType::Bytes => self.write("BYTES"),
1113            DataType::Json => self.write("JSON"),
1114            DataType::Jsonb => self.write("JSONB"),
1115            DataType::Uuid => self.write("UUID"),
1116            DataType::Array(inner) => {
1117                self.write("ARRAY");
1118                if let Some(inner) = inner {
1119                    self.write("<");
1120                    self.gen_data_type(inner);
1121                    self.write(">");
1122                }
1123            }
1124            DataType::Map { key, value } => {
1125                self.write("MAP<");
1126                self.gen_data_type(key);
1127                self.write(", ");
1128                self.gen_data_type(value);
1129                self.write(">");
1130            }
1131            DataType::Struct(fields) => {
1132                self.write("STRUCT<");
1133                for (i, (name, dt)) in fields.iter().enumerate() {
1134                    if i > 0 {
1135                        self.write(", ");
1136                    }
1137                    self.write(name);
1138                    self.write(" ");
1139                    self.gen_data_type(dt);
1140                }
1141                self.write(">");
1142            }
1143            DataType::Tuple(types) => {
1144                self.write("TUPLE(");
1145                for (i, dt) in types.iter().enumerate() {
1146                    if i > 0 {
1147                        self.write(", ");
1148                    }
1149                    self.gen_data_type(dt);
1150                }
1151                self.write(")");
1152            }
1153            DataType::Null => self.write("NULL"),
1154            DataType::Variant => self.write("VARIANT"),
1155            DataType::Object => self.write("OBJECT"),
1156            DataType::Xml => self.write("XML"),
1157            DataType::Inet => self.write("INET"),
1158            DataType::Cidr => self.write("CIDR"),
1159            DataType::Macaddr => self.write("MACADDR"),
1160            DataType::Bit(len) => {
1161                self.write("BIT");
1162                if let Some(n) = len {
1163                    self.write(&format!("({n})"));
1164                }
1165            }
1166            DataType::Money => self.write("MONEY"),
1167            DataType::Serial => self.write("SERIAL"),
1168            DataType::BigSerial => self.write("BIGSERIAL"),
1169            DataType::SmallSerial => self.write("SMALLSERIAL"),
1170            DataType::Regclass => self.write("REGCLASS"),
1171            DataType::Regtype => self.write("REGTYPE"),
1172            DataType::Hstore => self.write("HSTORE"),
1173            DataType::Geography => self.write("GEOGRAPHY"),
1174            DataType::Geometry => self.write("GEOMETRY"),
1175            DataType::Super => self.write("SUPER"),
1176            DataType::Unknown(name) => self.write(name),
1177        }
1178    }
1179
1180    // ══════════════════════════════════════════════════════════════
1181    // Expressions
1182    // ══════════════════════════════════════════════════════════════
1183
1184    fn gen_expr_list(&mut self, exprs: &[Expr]) {
1185        for (i, expr) in exprs.iter().enumerate() {
1186            if i > 0 {
1187                self.write(", ");
1188            }
1189            self.gen_expr(expr);
1190        }
1191    }
1192
1193    fn gen_expr(&mut self, expr: &Expr) {
1194        match expr {
1195            Expr::Column { table, name, quote_style, table_quote_style } => {
1196                if let Some(t) = table {
1197                    self.write_quoted(t, *table_quote_style);
1198                    self.write(".");
1199                }
1200                self.write_quoted(name, *quote_style);
1201            }
1202            Expr::Number(n) => self.write(n),
1203            Expr::StringLiteral(s) => {
1204                self.write("'");
1205                self.write(&s.replace('\'', "''"));
1206                self.write("'");
1207            }
1208            Expr::Boolean(b) => self.write(if *b { "TRUE" } else { "FALSE" }),
1209            Expr::Null => self.write("NULL"),
1210            Expr::Default => self.write_keyword("DEFAULT"),
1211            Expr::Wildcard | Expr::Star => self.write("*"),
1212
1213            Expr::BinaryOp { left, op, right } => {
1214                self.gen_expr(left);
1215                let op_str = match op {
1216                    BinaryOperator::Plus => " + ",
1217                    BinaryOperator::Minus => " - ",
1218                    BinaryOperator::Multiply => " * ",
1219                    BinaryOperator::Divide => " / ",
1220                    BinaryOperator::Modulo => " % ",
1221                    BinaryOperator::Eq => " = ",
1222                    BinaryOperator::Neq => " <> ",
1223                    BinaryOperator::Lt => " < ",
1224                    BinaryOperator::Gt => " > ",
1225                    BinaryOperator::LtEq => " <= ",
1226                    BinaryOperator::GtEq => " >= ",
1227                    BinaryOperator::And => " AND ",
1228                    BinaryOperator::Or => " OR ",
1229                    BinaryOperator::Xor => " XOR ",
1230                    BinaryOperator::Concat => " || ",
1231                    BinaryOperator::BitwiseAnd => " & ",
1232                    BinaryOperator::BitwiseOr => " | ",
1233                    BinaryOperator::BitwiseXor => " ^ ",
1234                    BinaryOperator::ShiftLeft => " << ",
1235                    BinaryOperator::ShiftRight => " >> ",
1236                    BinaryOperator::Arrow => " -> ",
1237                    BinaryOperator::DoubleArrow => " ->> ",
1238                };
1239                self.write(op_str);
1240                self.gen_expr(right);
1241            }
1242            Expr::UnaryOp { op, expr } => {
1243                let op_str = match op {
1244                    UnaryOperator::Not => "NOT ",
1245                    UnaryOperator::Minus => "-",
1246                    UnaryOperator::Plus => "+",
1247                    UnaryOperator::BitwiseNot => "~",
1248                };
1249                self.write(op_str);
1250                self.gen_expr(expr);
1251            }
1252            Expr::Function { name, args, distinct, filter, over } => {
1253                self.write(name);
1254                self.write("(");
1255                if *distinct {
1256                    self.write_keyword("DISTINCT ");
1257                }
1258                self.gen_expr_list(args);
1259                self.write(")");
1260
1261                if let Some(filter_expr) = filter {
1262                    self.write(" ");
1263                    self.write_keyword("FILTER (WHERE ");
1264                    self.gen_expr(filter_expr);
1265                    self.write(")");
1266                }
1267                if let Some(spec) = over {
1268                    self.write(" ");
1269                    self.write_keyword("OVER ");
1270                    if let Some(wref) = &spec.window_ref {
1271                        if spec.partition_by.is_empty() && spec.order_by.is_empty() && spec.frame.is_none() {
1272                            self.write(wref);
1273                        } else {
1274                            self.write("(");
1275                            self.gen_window_spec(spec);
1276                            self.write(")");
1277                        }
1278                    } else {
1279                        self.write("(");
1280                        self.gen_window_spec(spec);
1281                        self.write(")");
1282                    }
1283                }
1284            }
1285            Expr::Between { expr, low, high, negated } => {
1286                self.gen_expr(expr);
1287                if *negated {
1288                    self.write(" ");
1289                    self.write_keyword("NOT");
1290                }
1291                self.write(" ");
1292                self.write_keyword("BETWEEN ");
1293                self.gen_expr(low);
1294                self.write(" ");
1295                self.write_keyword("AND ");
1296                self.gen_expr(high);
1297            }
1298            Expr::InList { expr, list, negated } => {
1299                self.gen_expr(expr);
1300                if *negated {
1301                    self.write(" ");
1302                    self.write_keyword("NOT");
1303                }
1304                self.write(" ");
1305                self.write_keyword("IN (");
1306                self.gen_expr_list(list);
1307                self.write(")");
1308            }
1309            Expr::InSubquery { expr, subquery, negated } => {
1310                self.gen_expr(expr);
1311                if *negated {
1312                    self.write(" ");
1313                    self.write_keyword("NOT");
1314                }
1315                self.write(" ");
1316                self.write_keyword("IN (");
1317                self.gen_statement(subquery);
1318                self.write(")");
1319            }
1320            Expr::IsNull { expr, negated } => {
1321                self.gen_expr(expr);
1322                if *negated {
1323                    self.write(" ");
1324                    self.write_keyword("IS NOT NULL");
1325                } else {
1326                    self.write(" ");
1327                    self.write_keyword("IS NULL");
1328                }
1329            }
1330            Expr::IsBool { expr, value, negated } => {
1331                self.gen_expr(expr);
1332                self.write(" ");
1333                match (negated, value) {
1334                    (false, true) => self.write_keyword("IS TRUE"),
1335                    (false, false) => self.write_keyword("IS FALSE"),
1336                    (true, true) => self.write_keyword("IS NOT TRUE"),
1337                    (true, false) => self.write_keyword("IS NOT FALSE"),
1338                }
1339            }
1340            Expr::Like { expr, pattern, negated, escape } => {
1341                self.gen_expr(expr);
1342                if *negated {
1343                    self.write(" ");
1344                    self.write_keyword("NOT");
1345                }
1346                self.write(" ");
1347                self.write_keyword("LIKE ");
1348                self.gen_expr(pattern);
1349                if let Some(esc) = escape {
1350                    self.write(" ");
1351                    self.write_keyword("ESCAPE ");
1352                    self.gen_expr(esc);
1353                }
1354            }
1355            Expr::ILike { expr, pattern, negated, escape } => {
1356                self.gen_expr(expr);
1357                if *negated {
1358                    self.write(" ");
1359                    self.write_keyword("NOT");
1360                }
1361                self.write(" ");
1362                self.write_keyword("ILIKE ");
1363                self.gen_expr(pattern);
1364                if let Some(esc) = escape {
1365                    self.write(" ");
1366                    self.write_keyword("ESCAPE ");
1367                    self.gen_expr(esc);
1368                }
1369            }
1370            Expr::Case { operand, when_clauses, else_clause } => {
1371                self.write_keyword("CASE");
1372                if let Some(op) = operand {
1373                    self.write(" ");
1374                    self.gen_expr(op);
1375                }
1376                for (cond, result) in when_clauses {
1377                    self.write(" ");
1378                    self.write_keyword("WHEN ");
1379                    self.gen_expr(cond);
1380                    self.write(" ");
1381                    self.write_keyword("THEN ");
1382                    self.gen_expr(result);
1383                }
1384                if let Some(el) = else_clause {
1385                    self.write(" ");
1386                    self.write_keyword("ELSE ");
1387                    self.gen_expr(el);
1388                }
1389                self.write(" ");
1390                self.write_keyword("END");
1391            }
1392            Expr::Nested(inner) => {
1393                self.write("(");
1394                self.gen_expr(inner);
1395                self.write(")");
1396            }
1397            Expr::Subquery(query) => {
1398                self.write("(");
1399                self.gen_statement(query);
1400                self.write(")");
1401            }
1402            Expr::Exists { subquery, negated } => {
1403                if *negated {
1404                    self.write_keyword("NOT ");
1405                }
1406                self.write_keyword("EXISTS (");
1407                self.gen_statement(subquery);
1408                self.write(")");
1409            }
1410            Expr::Cast { expr, data_type } => {
1411                self.write_keyword("CAST(");
1412                self.gen_expr(expr);
1413                self.write(" ");
1414                self.write_keyword("AS ");
1415                self.gen_data_type(data_type);
1416                self.write(")");
1417            }
1418            Expr::TryCast { expr, data_type } => {
1419                self.write_keyword("TRY_CAST(");
1420                self.gen_expr(expr);
1421                self.write(" ");
1422                self.write_keyword("AS ");
1423                self.gen_data_type(data_type);
1424                self.write(")");
1425            }
1426            Expr::Extract { field, expr } => {
1427                self.write_keyword("EXTRACT(");
1428                self.gen_datetime_field(field);
1429                self.write(" ");
1430                self.write_keyword("FROM ");
1431                self.gen_expr(expr);
1432                self.write(")");
1433            }
1434            Expr::Interval { value, unit } => {
1435                self.write_keyword("INTERVAL ");
1436                self.gen_expr(value);
1437                if let Some(unit) = unit {
1438                    self.write(" ");
1439                    self.gen_datetime_field(unit);
1440                }
1441            }
1442            Expr::ArrayLiteral(items) => {
1443                self.write_keyword("ARRAY[");
1444                self.gen_expr_list(items);
1445                self.write("]");
1446            }
1447            Expr::Tuple(items) => {
1448                self.write("(");
1449                self.gen_expr_list(items);
1450                self.write(")");
1451            }
1452            Expr::Coalesce(items) => {
1453                self.write_keyword("COALESCE(");
1454                self.gen_expr_list(items);
1455                self.write(")");
1456            }
1457            Expr::If { condition, true_val, false_val } => {
1458                self.write_keyword("IF(");
1459                self.gen_expr(condition);
1460                self.write(", ");
1461                self.gen_expr(true_val);
1462                if let Some(fv) = false_val {
1463                    self.write(", ");
1464                    self.gen_expr(fv);
1465                }
1466                self.write(")");
1467            }
1468            Expr::NullIf { expr, r#else } => {
1469                self.write_keyword("NULLIF(");
1470                self.gen_expr(expr);
1471                self.write(", ");
1472                self.gen_expr(r#else);
1473                self.write(")");
1474            }
1475            Expr::Collate { expr, collation } => {
1476                self.gen_expr(expr);
1477                self.write(" ");
1478                self.write_keyword("COLLATE ");
1479                self.write(collation);
1480            }
1481            Expr::Parameter(p) => self.write(p),
1482            Expr::TypeExpr(dt) => self.gen_data_type(dt),
1483            Expr::QualifiedWildcard { table } => {
1484                self.write(table);
1485                self.write(".*");
1486            }
1487            Expr::Alias { expr, name } => {
1488                self.gen_expr(expr);
1489                self.write(" ");
1490                self.write_keyword("AS ");
1491                self.write(name);
1492            }
1493            Expr::ArrayIndex { expr, index } => {
1494                self.gen_expr(expr);
1495                self.write("[");
1496                self.gen_expr(index);
1497                self.write("]");
1498            }
1499            Expr::JsonAccess { expr, path, as_text } => {
1500                self.gen_expr(expr);
1501                if *as_text {
1502                    self.write("->>");
1503                } else {
1504                    self.write("->");
1505                }
1506                self.gen_expr(path);
1507            }
1508            Expr::Lambda { params, body } => {
1509                if params.len() == 1 {
1510                    self.write(&params[0]);
1511                } else {
1512                    self.write("(");
1513                    self.write(&params.join(", "));
1514                    self.write(")");
1515                }
1516                self.write(" -> ");
1517                self.gen_expr(body);
1518            }
1519        }
1520    }
1521
1522    fn gen_window_spec(&mut self, spec: &WindowSpec) {
1523        if let Some(wref) = &spec.window_ref {
1524            self.write(wref);
1525            if !spec.partition_by.is_empty() || !spec.order_by.is_empty() || spec.frame.is_some() {
1526                self.write(" ");
1527            }
1528        }
1529        if !spec.partition_by.is_empty() {
1530            self.write_keyword("PARTITION BY ");
1531            self.gen_expr_list(&spec.partition_by);
1532        }
1533        if !spec.order_by.is_empty() {
1534            if !spec.partition_by.is_empty() {
1535                self.write(" ");
1536            }
1537            self.write_keyword("ORDER BY ");
1538            for (i, item) in spec.order_by.iter().enumerate() {
1539                if i > 0 {
1540                    self.write(", ");
1541                }
1542                self.gen_expr(&item.expr);
1543                if !item.ascending {
1544                    self.write(" ");
1545                    self.write_keyword("DESC");
1546                }
1547                if let Some(nulls_first) = item.nulls_first {
1548                    if nulls_first {
1549                        self.write(" ");
1550                        self.write_keyword("NULLS FIRST");
1551                    } else {
1552                        self.write(" ");
1553                        self.write_keyword("NULLS LAST");
1554                    }
1555                }
1556            }
1557        }
1558        if let Some(frame) = &spec.frame {
1559            self.write(" ");
1560            self.gen_window_frame(frame);
1561        }
1562    }
1563
1564    fn gen_window_frame(&mut self, frame: &WindowFrame) {
1565        match frame.kind {
1566            WindowFrameKind::Rows => self.write_keyword("ROWS "),
1567            WindowFrameKind::Range => self.write_keyword("RANGE "),
1568            WindowFrameKind::Groups => self.write_keyword("GROUPS "),
1569        }
1570        if let Some(end) = &frame.end {
1571            self.write_keyword("BETWEEN ");
1572            self.gen_window_frame_bound(&frame.start);
1573            self.write(" ");
1574            self.write_keyword("AND ");
1575            self.gen_window_frame_bound(end);
1576        } else {
1577            self.gen_window_frame_bound(&frame.start);
1578        }
1579    }
1580
1581    fn gen_window_frame_bound(&mut self, bound: &WindowFrameBound) {
1582        match bound {
1583            WindowFrameBound::CurrentRow => self.write_keyword("CURRENT ROW"),
1584            WindowFrameBound::Preceding(None) => self.write_keyword("UNBOUNDED PRECEDING"),
1585            WindowFrameBound::Preceding(Some(n)) => {
1586                self.gen_expr(n);
1587                self.write(" ");
1588                self.write_keyword("PRECEDING");
1589            }
1590            WindowFrameBound::Following(None) => self.write_keyword("UNBOUNDED FOLLOWING"),
1591            WindowFrameBound::Following(Some(n)) => {
1592                self.gen_expr(n);
1593                self.write(" ");
1594                self.write_keyword("FOLLOWING");
1595            }
1596        }
1597    }
1598
1599    fn gen_datetime_field(&mut self, field: &DateTimeField) {
1600        let name = match field {
1601            DateTimeField::Year => "YEAR",
1602            DateTimeField::Quarter => "QUARTER",
1603            DateTimeField::Month => "MONTH",
1604            DateTimeField::Week => "WEEK",
1605            DateTimeField::Day => "DAY",
1606            DateTimeField::DayOfWeek => "DOW",
1607            DateTimeField::DayOfYear => "DOY",
1608            DateTimeField::Hour => "HOUR",
1609            DateTimeField::Minute => "MINUTE",
1610            DateTimeField::Second => "SECOND",
1611            DateTimeField::Millisecond => "MILLISECOND",
1612            DateTimeField::Microsecond => "MICROSECOND",
1613            DateTimeField::Nanosecond => "NANOSECOND",
1614            DateTimeField::Epoch => "EPOCH",
1615            DateTimeField::Timezone => "TIMEZONE",
1616            DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
1617            DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
1618        };
1619        self.write(name);
1620    }
1621}
1622
1623impl Default for Generator {
1624    fn default() -> Self {
1625        Self::new()
1626    }
1627}
1628
1629#[cfg(test)]
1630mod tests {
1631    use super::*;
1632    use crate::parser::Parser;
1633
1634    fn roundtrip(sql: &str) -> String {
1635        let stmt = Parser::new(sql).unwrap().parse_statement().unwrap();
1636        let mut g = Generator::new();
1637        g.generate(&stmt)
1638    }
1639
1640    #[test]
1641    fn test_select_roundtrip() {
1642        assert_eq!(roundtrip("SELECT a, b FROM t"), "SELECT a, b FROM t");
1643    }
1644
1645    #[test]
1646    fn test_select_where() {
1647        assert_eq!(
1648            roundtrip("SELECT x FROM t WHERE x > 10"),
1649            "SELECT x FROM t WHERE x > 10"
1650        );
1651    }
1652
1653    #[test]
1654    fn test_select_wildcard() {
1655        assert_eq!(roundtrip("SELECT * FROM users"), "SELECT * FROM users");
1656    }
1657
1658    #[test]
1659    fn test_insert_values() {
1660        assert_eq!(
1661            roundtrip("INSERT INTO t (a, b) VALUES (1, 'hello')"),
1662            "INSERT INTO t (a, b) VALUES (1, 'hello')"
1663        );
1664    }
1665
1666    #[test]
1667    fn test_delete() {
1668        assert_eq!(
1669            roundtrip("DELETE FROM users WHERE id = 1"),
1670            "DELETE FROM users WHERE id = 1"
1671        );
1672    }
1673
1674    #[test]
1675    fn test_join() {
1676        assert_eq!(
1677            roundtrip("SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"),
1678            "SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"
1679        );
1680    }
1681
1682    #[test]
1683    fn test_create_table() {
1684        assert_eq!(
1685            roundtrip("CREATE TABLE users (id INT NOT NULL, name VARCHAR(255), email TEXT)"),
1686            "CREATE TABLE users (id INT NOT NULL, name VARCHAR(255), email TEXT)"
1687        );
1688    }
1689
1690    #[test]
1691    fn test_cte_roundtrip() {
1692        let sql = "WITH cte AS (SELECT 1 AS x) SELECT x FROM cte";
1693        assert_eq!(roundtrip(sql), "WITH cte AS (SELECT 1 AS x) SELECT x FROM cte");
1694    }
1695
1696    #[test]
1697    fn test_union_roundtrip() {
1698        let sql = "SELECT 1 UNION ALL SELECT 2";
1699        assert_eq!(roundtrip(sql), "SELECT 1 UNION ALL SELECT 2");
1700    }
1701
1702    #[test]
1703    fn test_cast_roundtrip() {
1704        assert_eq!(
1705            roundtrip("SELECT CAST(x AS INT) FROM t"),
1706            "SELECT CAST(x AS INT) FROM t"
1707        );
1708    }
1709
1710    #[test]
1711    fn test_exists_roundtrip() {
1712        assert_eq!(
1713            roundtrip("SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t2)"),
1714            "SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t2)"
1715        );
1716    }
1717
1718    #[test]
1719    fn test_extract_roundtrip() {
1720        assert_eq!(
1721            roundtrip("SELECT EXTRACT(YEAR FROM created_at) FROM t"),
1722            "SELECT EXTRACT(YEAR FROM created_at) FROM t"
1723        );
1724    }
1725
1726    #[test]
1727    fn test_window_function_roundtrip() {
1728        assert_eq!(
1729            roundtrip("SELECT ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) FROM emp"),
1730            "SELECT ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) FROM emp"
1731        );
1732    }
1733
1734    #[test]
1735    fn test_subquery_from_roundtrip() {
1736        assert_eq!(
1737            roundtrip("SELECT * FROM (SELECT 1 AS x) AS sub"),
1738            "SELECT * FROM (SELECT 1 AS x) AS sub"
1739        );
1740    }
1741
1742    #[test]
1743    fn test_in_subquery_roundtrip() {
1744        assert_eq!(
1745            roundtrip("SELECT * FROM t WHERE id IN (SELECT id FROM t2)"),
1746            "SELECT * FROM t WHERE id IN (SELECT id FROM t2)"
1747        );
1748    }
1749
1750    // ═══════════════════════════════════════════════════════════════
1751    // Pretty-print tests
1752    // ═══════════════════════════════════════════════════════════════
1753
1754    fn pretty_print(sql: &str) -> String {
1755        let stmt = Parser::new(sql).unwrap().parse_statement().unwrap();
1756        let mut g = Generator::pretty();
1757        g.generate(&stmt)
1758    }
1759
1760    #[test]
1761    fn test_pretty_simple_select() {
1762        assert_eq!(
1763            pretty_print("SELECT a, b, c FROM t"),
1764            "SELECT\n  a,\n  b,\n  c\nFROM\n  t"
1765        );
1766    }
1767
1768    #[test]
1769    fn test_pretty_select_where() {
1770        assert_eq!(
1771            pretty_print("SELECT a FROM t WHERE a > 1"),
1772            "SELECT\n  a\nFROM\n  t\nWHERE\n  a > 1"
1773        );
1774    }
1775
1776    #[test]
1777    fn test_pretty_select_group_by_having() {
1778        assert_eq!(
1779            pretty_print("SELECT a, COUNT(*) FROM t GROUP BY a HAVING COUNT(*) > 1"),
1780            "SELECT\n  a,\n  COUNT(*)\nFROM\n  t\nGROUP BY\n  a\nHAVING\n  COUNT(*) > 1"
1781        );
1782    }
1783
1784    #[test]
1785    fn test_pretty_select_order_by_limit() {
1786        assert_eq!(
1787            pretty_print("SELECT a FROM t ORDER BY a DESC LIMIT 10"),
1788            "SELECT\n  a\nFROM\n  t\nORDER BY\n  a DESC\nLIMIT 10"
1789        );
1790    }
1791
1792    #[test]
1793    fn test_pretty_join() {
1794        assert_eq!(
1795            pretty_print("SELECT a.id, b.name FROM a INNER JOIN b ON a.id = b.a_id"),
1796            "SELECT\n  a.id,\n  b.name\nFROM\n  a\nINNER JOIN\n  b\n  ON a.id = b.a_id"
1797        );
1798    }
1799
1800    #[test]
1801    fn test_pretty_cte() {
1802        assert_eq!(
1803            pretty_print("WITH cte AS (SELECT 1 AS x) SELECT x FROM cte"),
1804            "WITH cte AS (\n  SELECT\n    1 AS x\n)\nSELECT\n  x\nFROM\n  cte"
1805        );
1806    }
1807
1808    #[test]
1809    fn test_pretty_union() {
1810        assert_eq!(
1811            pretty_print("SELECT 1 UNION ALL SELECT 2"),
1812            "SELECT\n  1\nUNION ALL\nSELECT\n  2"
1813        );
1814    }
1815
1816    #[test]
1817    fn test_pretty_insert() {
1818        assert_eq!(
1819            pretty_print("INSERT INTO t (a, b) VALUES (1, 'hello'), (2, 'world')"),
1820            "INSERT INTO t (a, b)\nVALUES\n  (1, 'hello'),\n  (2, 'world')"
1821        );
1822    }
1823
1824    #[test]
1825    fn test_pretty_update() {
1826        assert_eq!(
1827            pretty_print("UPDATE t SET a = 1, b = 2 WHERE c = 3"),
1828            "UPDATE t\nSET\n  a = 1,\n  b = 2\nWHERE\n  c = 3"
1829        );
1830    }
1831
1832    #[test]
1833    fn test_pretty_delete() {
1834        assert_eq!(
1835            pretty_print("DELETE FROM t WHERE id = 1"),
1836            "DELETE FROM t\nWHERE\n  id = 1"
1837        );
1838    }
1839
1840    #[test]
1841    fn test_pretty_create_table() {
1842        assert_eq!(
1843            pretty_print("CREATE TABLE t (id INT NOT NULL, name VARCHAR(255), email TEXT)"),
1844            "CREATE TABLE t (\n  id INT NOT NULL,\n  name VARCHAR(255),\n  email TEXT\n)"
1845        );
1846    }
1847
1848    #[test]
1849    fn test_pretty_complex_query() {
1850        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";
1851        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";
1852        assert_eq!(pretty_print(sql), expected);
1853    }
1854
1855    #[test]
1856    fn test_pretty_select_distinct() {
1857        assert_eq!(
1858            pretty_print("SELECT DISTINCT a, b FROM t"),
1859            "SELECT DISTINCT\n  a,\n  b\nFROM\n  t"
1860        );
1861    }
1862}