1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use ::sea_orm_migration::prelude::MigratorTrait;
#[cfg(feature = "tokio")]
use ::tokio::runtime::Builder;
#[cfg(feature = "tokio")]
use ::tokio::runtime::Runtime;
use crate::build_db_connection;
use crate::DbConnection;
use crate::queries::get_table_schemas;
use crate::queries::TableSchema;
#[cfg(feature = "tokio")]
pub fn assert_migrator_reversible<'a, M>(migrator: M, db_conn: Option<DbConnection<'a>>)
where
M: MigratorTrait,
{
build_tokio_runtime()
.block_on(async move { assert_migrator_reversible_async(migrator, db_conn).await });
}
pub async fn assert_migrator_reversible_async<'a, M>(migrator: M, db_conn: Option<DbConnection<'a>>)
where
M: MigratorTrait,
{
let maybe_index = find_index_of_non_reversible_migration_async(migrator, db_conn).await;
if let Some(index) = maybe_index {
panic!("Migration at index {} is not reversible", index);
}
}
#[cfg(feature = "tokio")]
pub fn find_index_of_non_reversible_migration<'a, M>(
migrator: M,
db_conn: Option<DbConnection<'a>>,
) -> Option<usize>
where
M: MigratorTrait,
{
build_tokio_runtime().block_on(async move {
find_index_of_non_reversible_migration_async(migrator, db_conn).await
})
}
pub async fn find_index_of_non_reversible_migration_async<'a, M>(
_migrator: M,
db_conn: Option<DbConnection<'a>>,
) -> Option<usize>
where
M: MigratorTrait,
{
let db_connection = build_db_connection(db_conn).await;
let num_migrations = M::migrations().len();
let mut migration_step_schemas: Vec<Vec<TableSchema>> = Vec::with_capacity(num_migrations);
for _ in 0..num_migrations {
let table_schemas = get_table_schemas(&db_connection).await;
migration_step_schemas.push(table_schemas);
<M as MigratorTrait>::up(&db_connection, Some(1))
.await
.expect("expect migration up should succeed");
}
for i in 0..num_migrations {
<M as MigratorTrait>::down(&db_connection, Some(1))
.await
.expect("expect migration down should succeed");
let down_table_schemas = get_table_schemas(&db_connection).await;
let up_table_schemas = migration_step_schemas
.pop()
.expect("expect up table schemas should exist");
if down_table_schemas != up_table_schemas {
return Some(num_migrations - i - 1);
}
}
None
}
#[cfg(feature = "tokio")]
fn build_tokio_runtime() -> Runtime {
Builder::new_current_thread()
.enable_time()
.enable_io()
.build()
.expect("Expect to be able to start Tokio runtime for testing")
}