use toolu_orm_connection::DbConnection;
use toolu_orm_core::dialect::Dialect;
use toolu_orm_core::error::DbCoreError;
use toolu_orm_core::value::Value;
use super::ddl::migrations_table_ddl;
use super::error::{map_db, MigrateError};
struct AppliedMigration {
name: String,
}
#[cfg(orm_core_has_postgres)]
fn map_pg(row: &toolu_orm_core::tokio_postgres::Row) -> Result<AppliedMigration, DbCoreError> {
let name: String = row
.try_get(0)
.map_err(|e: toolu_orm_core::tokio_postgres::Error| DbCoreError::RowMapping(e.to_string()))?;
Ok(AppliedMigration { name })
}
#[cfg(orm_core_has_libsql)]
fn map_libsql(row: &toolu_orm_core::libsql::Row) -> Result<AppliedMigration, DbCoreError> {
let name: String = row
.get::<String>(0)
.map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
Ok(AppliedMigration { name })
}
#[cfg(orm_core_has_rusqlite)]
fn map_rusqlite(row: &toolu_orm_core::rusqlite::Row<'_>) -> Result<AppliedMigration, DbCoreError> {
let name: String = row
.get(0)
.map_err(|e| DbCoreError::RowMapping(e.to_string()))?;
Ok(AppliedMigration { name })
}
toolu_orm_core::impl_from_row_for!(single
cfg(all(orm_core_has_libsql, not(orm_core_has_postgres), not(orm_core_has_rusqlite))),
AppliedMigration, &["name"], from_row, toolu_orm_core::libsql::Row, map_libsql);
toolu_orm_core::impl_from_row_for!(single
cfg(all(orm_core_has_postgres, not(orm_core_has_libsql), not(orm_core_has_rusqlite))),
AppliedMigration, &["name"], from_row, toolu_orm_core::tokio_postgres::Row, map_pg);
toolu_orm_core::impl_from_row_for!(dual
cfg(all(orm_core_has_postgres, orm_core_has_libsql, not(orm_core_has_rusqlite))),
AppliedMigration, &["name"],
[from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
[from_libsql_row toolu_orm_core::libsql::Row => map_libsql]);
toolu_orm_core::impl_from_row_for!(dual
cfg(all(orm_core_has_postgres, orm_core_has_rusqlite, not(orm_core_has_libsql))),
AppliedMigration, &["name"],
[from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
[from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
toolu_orm_core::impl_from_row_for!(dual
cfg(all(orm_core_has_libsql, orm_core_has_rusqlite, not(orm_core_has_postgres))),
AppliedMigration, &["name"],
[from_libsql_row toolu_orm_core::libsql::Row => map_libsql],
[from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
toolu_orm_core::impl_from_row_for!(triple
cfg(all(orm_core_has_postgres, orm_core_has_libsql, orm_core_has_rusqlite)),
AppliedMigration, &["name"],
[from_pg_row toolu_orm_core::tokio_postgres::Row => map_pg],
[from_libsql_row toolu_orm_core::libsql::Row => map_libsql],
[from_rusqlite_row toolu_orm_core::rusqlite::Row<'_> => map_rusqlite]);
pub async fn record_migration(
conn: &impl DbConnection,
name: &str,
hash: &str,
dialect: Dialect,
) -> Result<(), MigrateError> {
let sql = match dialect {
Dialect::Sqlite => "INSERT INTO _migrations (name, hash) VALUES (?1, ?2)",
Dialect::Postgres => "INSERT INTO _migrations (name, hash) VALUES ($1, $2)",
};
conn
.execute_sql(
sql,
vec![Value::Text(name.to_owned()), Value::Text(hash.to_owned())],
)
.await
.map_err(|e| map_db(&e))?;
Ok(())
}
pub async fn get_applied_migrations(conn: &impl DbConnection) -> Result<Vec<String>, MigrateError> {
let rows = conn
.query_map::<AppliedMigration>("SELECT name FROM _migrations ORDER BY id", vec![])
.await
.map_err(|e| map_db(&e))?;
Ok(rows.into_iter().map(|r| r.name).collect())
}
pub async fn ensure_migrations_table(
conn: &impl DbConnection,
dialect: Dialect,
) -> Result<(), MigrateError> {
let ddl = migrations_table_ddl(dialect);
conn.execute_batch(&ddl).await.map_err(|e| map_db(&e))?;
Ok(())
}