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}
41
42impl std::fmt::Display for Orm {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 match self {
45 Orm::Diesel => write!(f, "diesel"),
46 Orm::Sqlx => write!(f, "sqlx"),
47 Orm::SeaOrm => write!(f, "seaorm"),
48 }
49 }
50}
51
52impl std::str::FromStr for Orm {
53 type Err = String;
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 match s.to_lowercase().as_str() {
56 "diesel" => Ok(Orm::Diesel),
57 "sqlx" => Ok(Orm::Sqlx),
58 "seaorm" | "sea-orm" | "sea_orm" => Ok(Orm::SeaOrm),
59 _ => Err(format!("unknown orm: '{s}'")),
60 }
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
66pub enum ColumnType {
67 Uuid,
69 Varchar,
71 VarcharN(u32),
73 Boolean,
75 DateTime,
77 Json,
79 Int,
81 SmallInt,
83 Text,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Hash)]
89pub enum OnDelete {
90 Cascade,
91 SetNull,
92 Restrict,
93 NoAction,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Hash)]
98pub struct ForeignKey {
99 pub references_table: String,
100 pub references_column: String,
101 pub on_delete: OnDelete,
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct ColumnDef {
107 pub name: String,
108 pub col_type: ColumnType,
109 pub nullable: bool,
110 pub primary_key: bool,
111 pub unique: bool,
112 pub default: Option<String>,
113 pub foreign_key: Option<ForeignKey>,
114}
115
116impl ColumnDef {
117 pub fn new(name: &str, col_type: ColumnType) -> Self {
119 Self {
120 name: name.to_string(),
121 col_type,
122 nullable: false,
123 primary_key: false,
124 unique: false,
125 default: None,
126 foreign_key: None,
127 }
128 }
129
130 pub fn nullable(mut self) -> Self {
131 self.nullable = true;
132 self
133 }
134
135 pub fn primary_key(mut self) -> Self {
136 self.primary_key = true;
137 self
138 }
139
140 pub fn unique(mut self) -> Self {
141 self.unique = true;
142 self
143 }
144
145 pub fn default(mut self, val: &str) -> Self {
146 self.default = Some(val.to_string());
147 self
148 }
149
150 pub fn references(mut self, table: &str, column: &str, on_delete: OnDelete) -> Self {
151 self.foreign_key = Some(ForeignKey {
152 references_table: table.to_string(),
153 references_column: column.to_string(),
154 on_delete,
155 });
156 self
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
162pub struct IndexDef {
163 pub name: String,
164 pub columns: Vec<String>,
165 pub unique: bool,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
170pub struct TableDef {
171 pub name: String,
172 pub columns: Vec<ColumnDef>,
173 pub indices: Vec<IndexDef>,
174}
175
176impl TableDef {
177 pub fn new(name: &str) -> Self {
178 Self {
179 name: name.to_string(),
180 columns: Vec::new(),
181 indices: Vec::new(),
182 }
183 }
184
185 pub fn column(mut self, col: ColumnDef) -> Self {
186 self.columns.push(col);
187 self
188 }
189
190 pub fn index(mut self, idx: IndexDef) -> Self {
191 self.indices.push(idx);
192 self
193 }
194
195 pub fn dependencies(&self) -> Vec<&str> {
197 self.columns
198 .iter()
199 .filter_map(|c| {
200 c.foreign_key
201 .as_ref()
202 .map(|fk| fk.references_table.as_str())
203 })
204 .filter(|t| *t != self.name)
205 .collect()
206 }
207
208 pub fn apply_prefix(&mut self, old_prefix: &str, new_prefix: &str) {
210 if self.name.starts_with(old_prefix) {
211 self.name = format!("{}{}", new_prefix, &self.name[old_prefix.len()..]);
212 }
213 for col in &mut self.columns {
214 if let Some(ref mut fk) = col.foreign_key
215 && fk.references_table.starts_with(old_prefix)
216 {
217 fk.references_table =
218 format!("{}{}", new_prefix, &fk.references_table[old_prefix.len()..]);
219 }
220 }
221 for idx in &mut self.indices {
222 if idx.name.starts_with(old_prefix) {
223 idx.name = format!("{}{}", new_prefix, &idx.name[old_prefix.len()..]);
224 }
225 }
226 }
227}