1use qail_core::prelude::*;
4
5pub fn cmd_to_sql(cmd: &QailCmd) -> String {
7 match cmd.action {
9 Action::Make => {
10 let mut sql = format!("CREATE TABLE {} (", cmd.table);
12 let cols: Vec<String> = cmd.columns.iter().filter_map(|col| {
13 if let Expr::Def { name, data_type, constraints } = col {
14 let mut col_def = format!("{} {}", name, data_type);
15 for c in constraints {
16 match c {
17 Constraint::PrimaryKey => col_def.push_str(" PRIMARY KEY"),
18 Constraint::Nullable => {},
19 Constraint::Unique => col_def.push_str(" UNIQUE"),
20 Constraint::Default(v) => col_def.push_str(&format!(" DEFAULT {}", v)),
21 _ => {},
22 }
23 }
24 Some(col_def)
25 } else {
26 None
27 }
28 }).collect();
29 sql.push_str(&cols.join(", "));
30 sql.push(')');
31 sql
32 },
33 Action::Drop => {
34 format!("DROP TABLE IF EXISTS {}", cmd.table)
35 },
36 Action::Alter => {
37 if let Some(Expr::Def { name, data_type, constraints }) = cmd.columns.first() {
39 let mut sql = format!("ALTER TABLE {} ADD COLUMN {} {}", cmd.table, name, data_type);
40 for c in constraints {
41 match c {
42 Constraint::Nullable => {},
43 Constraint::Unique => sql.push_str(" UNIQUE"),
44 Constraint::Default(v) => sql.push_str(&format!(" DEFAULT {}", v)),
45 _ => {},
46 }
47 }
48 return sql;
49 }
50 format!("ALTER TABLE {} ADD COLUMN ...", cmd.table)
51 },
52 Action::AlterDrop => {
53 if let Some(Expr::Named(name)) = cmd.columns.first() {
55 return format!("ALTER TABLE {} DROP COLUMN {}", cmd.table, name);
56 }
57 if let Some(Expr::Def { name, .. }) = cmd.columns.first() {
58 return format!("ALTER TABLE {} DROP COLUMN {}", cmd.table, name);
59 }
60 format!("ALTER TABLE {} DROP COLUMN ...", cmd.table)
61 },
62 Action::Index => {
63 if let Some(ref idx) = cmd.index_def {
64 let unique = if idx.unique { "UNIQUE " } else { "" };
65 return format!("CREATE {}INDEX {} ON {} ({})",
66 unique, idx.name, cmd.table, idx.columns.join(", "));
67 }
68 format!("CREATE INDEX ON {} (...)", cmd.table)
69 },
70 Action::DropIndex => {
71 if let Some(ref idx) = cmd.index_def {
72 return format!("DROP INDEX IF EXISTS {}", idx.name);
73 }
74 "DROP INDEX ...".to_string()
75 },
76 Action::Mod => {
77 format!("ALTER TABLE {} RENAME COLUMN ... TO ...", cmd.table)
79 },
80 _ => format!("-- Unsupported action: {:?}", cmd.action),
81 }
82}
83
84pub fn generate_rollback_sql(cmd: &QailCmd) -> String {
86 match cmd.action {
87 Action::Make => {
88 format!("DROP TABLE IF EXISTS {}", cmd.table)
89 },
90 Action::Drop => {
91 format!("-- Cannot auto-rollback DROP TABLE {} (data lost)", cmd.table)
92 },
93 Action::Alter => {
94 if let Some(col) = cmd.columns.first() {
96 if let Expr::Def { name, .. } = col {
97 return format!("ALTER TABLE {} DROP COLUMN {}", cmd.table, name);
98 }
99 }
100 format!("-- Cannot determine rollback for ALTER on {}", cmd.table)
101 },
102 Action::AlterDrop => {
103 format!("-- Cannot auto-rollback DROP COLUMN on {} (data lost)", cmd.table)
105 },
106 Action::Index => {
107 if let Some(ref idx) = cmd.index_def {
108 return format!("DROP INDEX IF EXISTS {}", idx.name);
109 }
110 "-- Cannot determine index name for rollback".to_string()
111 },
112 Action::DropIndex => {
113 format!("-- Cannot auto-rollback DROP INDEX (need original definition)")
114 },
115 Action::Mod => {
116 format!("-- RENAME operation: reverse manually")
117 },
118 _ => format!("-- No rollback for {:?}", cmd.action),
119 }
120}
121
122pub fn generate_down_sql(cmd: &QailCmd) -> String {
124 generate_rollback_sql(cmd)
125}