toolu_orm_cli/migrate/
store.rs1use toolu_orm_connection::DbConnection;
4use toolu_orm_core::dialect::Dialect;
5use toolu_orm_core::error::DbCoreError;
6use toolu_orm_core::value::Value;
7
8use super::ddl::migrations_table_ddl;
9use super::error::{map_db, MigrateError};
10
11struct AppliedMigration {
12 name: String,
13}
14
15#[cfg(orm_core_has_postgres)]
16fn map_pg(row: &toolu_orm_core::tokio_postgres::Row) -> Result<AppliedMigration, DbCoreError> {
17 let name: String = row
18 .try_get(0)
19 .map_err(|e: toolu_orm_core::tokio_postgres::Error| DbCoreError::RowMapping(e.to_string()))?;
20 Ok(AppliedMigration { name })
21}
22
23#[cfg(orm_core_has_libsql)]
24fn map_libsql(row: &toolu_orm_core::libsql::Row) -> Result<AppliedMigration, DbCoreError> {
25 let name: String = row
26 .get::<String>(0)
27 .map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
28 Ok(AppliedMigration { name })
29}
30
31#[cfg(orm_core_has_rusqlite)]
32fn map_rusqlite(row: &toolu_orm_core::rusqlite::Row<'_>) -> Result<AppliedMigration, DbCoreError> {
33 let name: String = row
34 .get(0)
35 .map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
36 Ok(AppliedMigration { name })
37}
38
39toolu_orm_core::impl_from_row_for!(single
44 cfg(all(orm_core_has_libsql, not(orm_core_has_postgres), not(orm_core_has_rusqlite))),
45 AppliedMigration, &["name"], from_row, toolu_orm_core::libsql::Row, map_libsql);
46
47toolu_orm_core::impl_from_row_for!(single
48 cfg(all(orm_core_has_postgres, not(orm_core_has_libsql), not(orm_core_has_rusqlite))),
49 AppliedMigration, &["name"], from_row, toolu_orm_core::tokio_postgres::Row, map_pg);
50
51toolu_orm_core::impl_from_row_for!(dual
52 cfg(all(orm_core_has_postgres, orm_core_has_libsql, not(orm_core_has_rusqlite))),
53 AppliedMigration, &["name"],
54 [from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
55 [from_libsql_row toolu_orm_core::libsql::Row => map_libsql]);
56
57toolu_orm_core::impl_from_row_for!(dual
58 cfg(all(orm_core_has_postgres, orm_core_has_rusqlite, not(orm_core_has_libsql))),
59 AppliedMigration, &["name"],
60 [from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
61 [from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
62
63toolu_orm_core::impl_from_row_for!(dual
64 cfg(all(orm_core_has_libsql, orm_core_has_rusqlite, not(orm_core_has_postgres))),
65 AppliedMigration, &["name"],
66 [from_libsql_row toolu_orm_core::libsql::Row => map_libsql],
67 [from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
68
69toolu_orm_core::impl_from_row_for!(triple
70 cfg(all(orm_core_has_postgres, orm_core_has_libsql, orm_core_has_rusqlite)),
71 AppliedMigration, &["name"],
72 [from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
73 [from_libsql_row toolu_orm_core::libsql::Row => map_libsql],
74 [from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
75
76pub async fn record_migration(
80 conn: &impl DbConnection,
81 name: &str,
82 hash: &str,
83 dialect: Dialect,
84) -> Result<(), MigrateError> {
85 let sql = match dialect {
86 Dialect::Sqlite => "INSERT INTO _migrations (name, hash) VALUES (?1, ?2)",
87 Dialect::Postgres => "INSERT INTO _migrations (name, hash) VALUES ($1, $2)",
88 };
89 conn
90 .execute_sql(
91 sql,
92 vec![Value::Text(name.to_owned()), Value::Text(hash.to_owned())],
93 )
94 .await
95 .map_err(|e| map_db(&e))?;
96 Ok(())
97}
98
99pub async fn get_applied_migrations(conn: &impl DbConnection) -> Result<Vec<String>, MigrateError> {
103 let rows = conn
104 .query_map::<AppliedMigration>("SELECT name FROM _migrations ORDER BY id", vec![])
105 .await
106 .map_err(|e| map_db(&e))?;
107 Ok(rows.into_iter().map(|r| r.name).collect())
108}
109
110pub async fn ensure_migrations_table(
114 conn: &impl DbConnection,
115 dialect: Dialect,
116) -> Result<(), MigrateError> {
117 let ddl = migrations_table_ddl(dialect);
118 conn.execute_batch(&ddl).await.map_err(|e| map_db(&e))?;
119 Ok(())
120}