sea_orm_migration/migrator/
with_self.rs1use super::{Migration, MigrationStatus, exec::*};
2use crate::{IntoSchemaManagerConnection, MigrationTrait, SchemaManager, seaql_migrations};
3use sea_orm::sea_query::IntoIden;
4use sea_orm::{ConnectionTrait, DbErr, DynIden};
5
6use tracing::info;
7
8#[async_trait::async_trait]
10pub trait MigratorTraitSelf: Sized + Send + Sync {
11 fn migrations(&self) -> Vec<Box<dyn MigrationTrait>>;
13
14 fn migration_table_name(&self) -> DynIden {
16 seaql_migrations::Entity.into_iden()
17 }
18
19 fn get_migration_files(&self) -> Vec<Migration> {
21 self.migrations()
22 .into_iter()
23 .map(|migration| Migration {
24 migration,
25 status: MigrationStatus::Pending,
26 })
27 .collect()
28 }
29
30 async fn get_migration_models<C>(&self, db: &C) -> Result<Vec<seaql_migrations::Model>, DbErr>
32 where
33 C: ConnectionTrait,
34 {
35 self.install(db).await?;
36 get_migration_models(db, self.migration_table_name()).await
37 }
38
39 async fn get_migration_with_status<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
41 where
42 C: ConnectionTrait,
43 {
44 self.install(db).await?;
45 get_migration_with_status(
46 self.get_migration_files(),
47 self.get_migration_models(db).await?,
48 )
49 }
50
51 async fn get_pending_migrations<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
53 where
54 C: ConnectionTrait,
55 {
56 self.install(db).await?;
57 Ok(self
58 .get_migration_with_status(db)
59 .await?
60 .into_iter()
61 .filter(|file| file.status == MigrationStatus::Pending)
62 .collect())
63 }
64
65 async fn get_applied_migrations<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
67 where
68 C: ConnectionTrait,
69 {
70 self.install(db).await?;
71 Ok(self
72 .get_migration_with_status(db)
73 .await?
74 .into_iter()
75 .filter(|file| file.status == MigrationStatus::Applied)
76 .collect())
77 }
78
79 async fn install<C>(&self, db: &C) -> Result<(), DbErr>
81 where
82 C: ConnectionTrait,
83 {
84 install(db, self.migration_table_name()).await
85 }
86
87 async fn status<C>(&self, db: &C) -> Result<(), DbErr>
89 where
90 C: ConnectionTrait,
91 {
92 self.install(db).await?;
93
94 info!("Checking migration status");
95
96 for Migration { migration, status } in self.get_migration_with_status(db).await? {
97 info!("Migration '{}'... {}", migration.name(), status);
98 }
99
100 Ok(())
101 }
102
103 async fn fresh<'c, C>(&self, db: C) -> Result<(), DbErr>
105 where
106 C: IntoSchemaManagerConnection<'c>,
107 {
108 let db = db.into_database_executor();
109 let manager = SchemaManager::new(db);
110 exec_fresh(self, &manager).await
111 }
112
113 async fn refresh<'c, C>(&self, db: C) -> Result<(), DbErr>
115 where
116 C: IntoSchemaManagerConnection<'c>,
117 {
118 let db = db.into_database_executor();
119 let manager = SchemaManager::new(db);
120 exec_down(self, &manager, None).await?;
121 exec_up(self, &manager, None).await
122 }
123
124 async fn reset<'c, C>(&self, db: C) -> Result<(), DbErr>
126 where
127 C: IntoSchemaManagerConnection<'c>,
128 {
129 let db = db.into_database_executor();
130 let manager = SchemaManager::new(db);
131 exec_down(self, &manager, None).await?;
132 uninstall(&manager, self.migration_table_name()).await
133 }
134
135 async fn uninstall<'c, C>(&self, db: C) -> Result<(), DbErr>
138 where
139 C: IntoSchemaManagerConnection<'c>,
140 {
141 let db = db.into_database_executor();
142 let manager = SchemaManager::new(db);
143 uninstall(&manager, self.migration_table_name()).await
144 }
145
146 async fn up<'c, C>(&self, db: C, steps: Option<u32>) -> Result<(), DbErr>
148 where
149 C: IntoSchemaManagerConnection<'c>,
150 {
151 let db = db.into_database_executor();
152 let manager = SchemaManager::new(db);
153 exec_up(self, &manager, steps).await
154 }
155
156 async fn down<'c, C>(&self, db: C, steps: Option<u32>) -> Result<(), DbErr>
158 where
159 C: IntoSchemaManagerConnection<'c>,
160 {
161 let db = db.into_database_executor();
162 let manager = SchemaManager::new(db);
163 exec_down(self, &manager, steps).await
164 }
165}
166
167#[async_trait::async_trait]
168impl<M> MigratorTraitSelf for M
169where
170 M: super::MigratorTrait + Sized + Send + Sync,
171{
172 fn migrations(&self) -> Vec<Box<dyn MigrationTrait>> {
173 M::migrations()
174 }
175
176 fn migration_table_name(&self) -> DynIden {
177 M::migration_table_name()
178 }
179
180 fn get_migration_files(&self) -> Vec<Migration> {
181 M::get_migration_files()
182 }
183
184 async fn get_migration_models<C>(&self, db: &C) -> Result<Vec<seaql_migrations::Model>, DbErr>
185 where
186 C: ConnectionTrait,
187 {
188 M::get_migration_models(db).await
189 }
190
191 async fn get_migration_with_status<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
192 where
193 C: ConnectionTrait,
194 {
195 M::get_migration_with_status(db).await
196 }
197
198 async fn get_pending_migrations<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
199 where
200 C: ConnectionTrait,
201 {
202 M::get_pending_migrations(db).await
203 }
204
205 async fn get_applied_migrations<C>(&self, db: &C) -> Result<Vec<Migration>, DbErr>
206 where
207 C: ConnectionTrait,
208 {
209 M::get_applied_migrations(db).await
210 }
211
212 async fn install<C>(&self, db: &C) -> Result<(), DbErr>
213 where
214 C: ConnectionTrait,
215 {
216 M::install(db).await
217 }
218
219 async fn status<C>(&self, db: &C) -> Result<(), DbErr>
221 where
222 C: ConnectionTrait,
223 {
224 M::status(db).await
225 }
226
227 async fn fresh<'c, C>(&self, db: C) -> Result<(), DbErr>
228 where
229 C: IntoSchemaManagerConnection<'c>,
230 {
231 M::fresh(db).await
232 }
233
234 async fn refresh<'c, C>(&self, db: C) -> Result<(), DbErr>
235 where
236 C: IntoSchemaManagerConnection<'c>,
237 {
238 M::refresh(db).await
239 }
240
241 async fn reset<'c, C>(&self, db: C) -> Result<(), DbErr>
242 where
243 C: IntoSchemaManagerConnection<'c>,
244 {
245 M::reset(db).await
246 }
247
248 async fn uninstall<'c, C>(&self, db: C) -> Result<(), DbErr>
249 where
250 C: IntoSchemaManagerConnection<'c>,
251 {
252 M::uninstall(db).await
253 }
254
255 async fn up<'c, C>(&self, db: C, steps: Option<u32>) -> Result<(), DbErr>
256 where
257 C: IntoSchemaManagerConnection<'c>,
258 {
259 M::up(db, steps).await
260 }
261
262 async fn down<'c, C>(&self, db: C, steps: Option<u32>) -> Result<(), DbErr>
263 where
264 C: IntoSchemaManagerConnection<'c>,
265 {
266 M::down(db, steps).await
267 }
268}
269
270async fn exec_fresh<M>(migrator: &M, manager: &SchemaManager<'_>) -> Result<(), DbErr>
271where
272 M: MigratorTraitSelf,
273{
274 let db = manager.get_connection();
275
276 migrator.install(db).await?;
277
278 drop_everything(db).await?;
279
280 exec_up(migrator, manager, None).await
281}
282
283async fn exec_up<M>(
284 migrator: &M,
285 manager: &SchemaManager<'_>,
286 steps: Option<u32>,
287) -> Result<(), DbErr>
288where
289 M: MigratorTraitSelf,
290{
291 let db = manager.get_connection();
292
293 migrator.install(db).await?;
294
295 exec_up_with(
296 manager,
297 steps,
298 migrator.get_pending_migrations(db).await?,
299 migrator.migration_table_name(),
300 )
301 .await
302}
303
304async fn exec_down<M>(
305 migrator: &M,
306 manager: &SchemaManager<'_>,
307 steps: Option<u32>,
308) -> Result<(), DbErr>
309where
310 M: MigratorTraitSelf,
311{
312 let db = manager.get_connection();
313
314 migrator.install(db).await?;
315
316 exec_down_with(
317 manager,
318 steps,
319 migrator.get_applied_migrations(db).await?,
320 migrator.migration_table_name(),
321 )
322 .await
323}