1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Dialect {
6 Postgres,
7 Sqlite,
8 Mysql,
9}
10
11impl std::fmt::Display for Dialect {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 match self {
14 Dialect::Postgres => write!(f, "postgres"),
15 Dialect::Sqlite => write!(f, "sqlite"),
16 Dialect::Mysql => write!(f, "mysql"),
17 }
18 }
19}
20
21impl std::str::FromStr for Dialect {
22 type Err = String;
23 fn from_str(s: &str) -> Result<Self, Self::Err> {
24 match s.to_lowercase().as_str() {
25 "postgres" | "postgresql" | "pg" => Ok(Dialect::Postgres),
26 "sqlite" => Ok(Dialect::Sqlite),
27 "mysql" | "mariadb" => Ok(Dialect::Mysql),
28 _ => Err(format!("unknown dialect: '{s}'")),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
35#[serde(rename_all = "lowercase")]
36pub enum Orm {
37 Diesel,
38 Sqlx,
39 SeaOrm,
40 Toasty,
41}
42
43impl std::fmt::Display for Orm {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 Orm::Diesel => write!(f, "diesel"),
47 Orm::Sqlx => write!(f, "sqlx"),
48 Orm::SeaOrm => write!(f, "seaorm"),
49 Orm::Toasty => write!(f, "toasty"),
50 }
51 }
52}
53
54impl std::str::FromStr for Orm {
55 type Err = String;
56 fn from_str(s: &str) -> Result<Self, Self::Err> {
57 match s.to_lowercase().as_str() {
58 "diesel" => Ok(Orm::Diesel),
59 "sqlx" => Ok(Orm::Sqlx),
60 "seaorm" | "sea-orm" | "sea_orm" => Ok(Orm::SeaOrm),
61 "toasty" => Ok(Orm::Toasty),
62 _ => Err(format!("unknown orm: '{s}'")),
63 }
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Hash)]
69pub enum ColumnType {
70 Uuid,
72 Varchar,
74 VarcharN(u32),
76 Boolean,
78 DateTime,
80 Json,
82 Int,
84 SmallInt,
86 Text,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub enum OnDelete {
93 Cascade,
94 SetNull,
95 Restrict,
96 NoAction,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101pub struct ForeignKey {
102 pub references_table: String,
103 pub references_column: String,
104 pub on_delete: OnDelete,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq)]
109pub struct ColumnDef {
110 pub name: String,
111 pub col_type: ColumnType,
112 pub nullable: bool,
113 pub primary_key: bool,
114 pub unique: bool,
115 pub default: Option<String>,
116 pub foreign_key: Option<ForeignKey>,
117}
118
119impl ColumnDef {
120 pub fn new(name: &str, col_type: ColumnType) -> Self {
122 Self {
123 name: name.to_string(),
124 col_type,
125 nullable: false,
126 primary_key: false,
127 unique: false,
128 default: None,
129 foreign_key: None,
130 }
131 }
132
133 pub fn nullable(mut self) -> Self {
134 self.nullable = true;
135 self
136 }
137
138 pub fn primary_key(mut self) -> Self {
139 self.primary_key = true;
140 self
141 }
142
143 pub fn unique(mut self) -> Self {
144 self.unique = true;
145 self
146 }
147
148 pub fn default(mut self, val: &str) -> Self {
149 self.default = Some(val.to_string());
150 self
151 }
152
153 pub fn references(mut self, table: &str, column: &str, on_delete: OnDelete) -> Self {
154 self.foreign_key = Some(ForeignKey {
155 references_table: table.to_string(),
156 references_column: column.to_string(),
157 on_delete,
158 });
159 self
160 }
161}
162
163#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct IndexDef {
166 pub name: String,
167 pub columns: Vec<String>,
168 pub unique: bool,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq)]
173pub struct TableDef {
174 pub name: String,
175 pub columns: Vec<ColumnDef>,
176 pub indices: Vec<IndexDef>,
177 pub description: Option<String>,
179}
180
181impl TableDef {
182 pub fn new(name: &str) -> Self {
183 Self {
184 name: name.to_string(),
185 columns: Vec::new(),
186 indices: Vec::new(),
187 description: None,
188 }
189 }
190
191 pub fn description(mut self, desc: &str) -> Self {
192 self.description = Some(desc.to_string());
193 self
194 }
195
196 pub fn column(mut self, col: ColumnDef) -> Self {
197 self.columns.push(col);
198 self
199 }
200
201 pub fn index(mut self, idx: IndexDef) -> Self {
202 self.indices.push(idx);
203 self
204 }
205
206 pub fn dependencies(&self) -> Vec<&str> {
208 self.columns
209 .iter()
210 .filter_map(|c| {
211 c.foreign_key
212 .as_ref()
213 .map(|fk| fk.references_table.as_str())
214 })
215 .filter(|t| *t != self.name)
216 .collect()
217 }
218
219 pub fn apply_prefix(&mut self, old_prefix: &str, new_prefix: &str) {
221 if self.name.starts_with(old_prefix) {
222 self.name = format!("{}{}", new_prefix, &self.name[old_prefix.len()..]);
223 }
224 for col in &mut self.columns {
225 if let Some(ref mut fk) = col.foreign_key
226 && fk.references_table.starts_with(old_prefix)
227 {
228 fk.references_table =
229 format!("{}{}", new_prefix, &fk.references_table[old_prefix.len()..]);
230 }
231 }
232 for idx in &mut self.indices {
233 if idx.name.starts_with(old_prefix) {
234 idx.name = format!("{}{}", new_prefix, &idx.name[old_prefix.len()..]);
235 }
236 }
237 }
238}