#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
#![allow(clippy::multiple_crate_versions)]
#[cfg(feature = "sqlite")]
pub async fn demonstrate_rollback_functionality() -> Result<(), crate::TestError> {
use std::sync::Arc;
use switchy_database::query::FilterableQuery as _;
use switchy_schema::migration::Migration;
use crate::{MigrationTestBuilder, create_empty_in_memory};
let db = create_empty_in_memory().await?;
let migration: Arc<dyn Migration<'static> + 'static> = Arc::new(TestMigration {
id: "001_create_users_table".to_string(),
operation: TestOperation::CreateUsers,
});
MigrationTestBuilder::new(vec![migration])
.with_rollback() .run(&*db)
.await?;
let tables = db
.select("sqlite_master")
.columns(&["name"])
.where_eq("type", "table")
.where_eq("name", "users")
.execute(&*db)
.await?;
assert!(tables.is_empty(), "Table should not exist after rollback");
Ok(())
}
#[cfg(feature = "sqlite")]
pub async fn demonstrate_complex_breakpoint_patterns() -> Result<(), crate::TestError> {
use std::sync::Arc;
use switchy_database::query::Expression as _;
use switchy_schema::migration::Migration;
use crate::{MigrationTestBuilder, create_empty_in_memory};
let db = create_empty_in_memory().await?;
let migrations: Vec<Arc<dyn Migration<'static> + 'static>> = vec![
Arc::new(TestMigration {
id: "001_create_users".to_string(),
operation: TestOperation::CreateUsers,
}),
Arc::new(TestMigration {
id: "002_add_email_column".to_string(),
operation: TestOperation::AddEmail,
}),
Arc::new(TestMigration {
id: "003_create_posts".to_string(),
operation: TestOperation::CreatePosts,
}),
];
MigrationTestBuilder::new(migrations)
.with_data_before("002_add_email_column", |db| {
Box::pin(async move {
db.insert("users")
.value("name", "Alice")
.execute(db)
.await?;
Ok(())
})
})
.with_data_after("002_add_email_column", |db| {
Box::pin(async move {
db.insert("users")
.value("name", "Bob")
.value("email", "bob@example.com")
.execute(db)
.await?;
Ok(())
})
})
.with_data_after("003_create_posts", |db| {
Box::pin(async move {
db.insert("posts")
.value("user_id", 1)
.value("title", "Alice Post")
.execute(db)
.await?;
db.insert("posts")
.value("user_id", 2)
.value("title", "Bob Post")
.execute(db)
.await?;
Ok(())
})
})
.run(&*db)
.await?;
let users = db
.select("users")
.columns(&["name", "email"])
.execute(&*db)
.await?;
assert_eq!(users.len(), 2, "Should have 2 users");
let alice = &users[0];
assert_eq!(alice.get("name").unwrap().as_str().unwrap(), "Alice");
assert!(alice.get("email").unwrap().is_null());
let bob = &users[1];
assert_eq!(bob.get("name").unwrap().as_str().unwrap(), "Bob");
assert_eq!(
bob.get("email").unwrap().as_str().unwrap(),
"bob@example.com"
);
let posts = db.select("posts").columns(&["title"]).execute(&*db).await?;
assert_eq!(posts.len(), 2, "Should have 2 posts");
Ok(())
}
#[cfg(feature = "sqlite")]
struct TestMigration {
id: String,
operation: TestOperation,
}
#[cfg(feature = "sqlite")]
enum TestOperation {
CreateUsers,
AddEmail,
CreatePosts,
}
#[cfg(feature = "sqlite")]
#[async_trait::async_trait]
impl switchy_schema::migration::Migration<'static> for TestMigration {
fn id(&self) -> &str {
&self.id
}
async fn up(
&self,
db: &dyn switchy_database::Database,
) -> Result<(), switchy_schema::MigrationError> {
use switchy_database::schema::{Column, DataType};
let column = |name: &str, data_type, nullable| Column {
name: name.to_string(),
nullable,
auto_increment: false,
data_type,
default: None,
};
match self.operation {
TestOperation::CreateUsers => {
db.create_table("users")
.column(column("id", DataType::Int, false))
.column(column("name", DataType::Text, false))
.primary_key("id")
.execute(db)
.await?;
}
TestOperation::AddEmail => {
db.alter_table("users")
.add_column("email".to_string(), DataType::Text, true, None)
.execute(db)
.await?;
}
TestOperation::CreatePosts => {
db.create_table("posts")
.column(column("id", DataType::Int, false))
.column(column("user_id", DataType::Int, true))
.column(column("title", DataType::Text, false))
.primary_key("id")
.execute(db)
.await?;
}
}
Ok(())
}
async fn down(
&self,
db: &dyn switchy_database::Database,
) -> Result<(), switchy_schema::MigrationError> {
match self.operation {
TestOperation::CreateUsers => {
db.drop_table("users").execute(db).await?;
}
TestOperation::AddEmail => {
db.alter_table("users")
.drop_column("email".to_string())
.execute(db)
.await?;
}
TestOperation::CreatePosts => {
db.drop_table("posts").execute(db).await?;
}
}
Ok(())
}
}
#[cfg(test)]
#[cfg(feature = "sqlite")]
mod tests {
use super::*;
#[switchy_async::test]
async fn test_rollback_demonstration() {
demonstrate_rollback_functionality().await.unwrap();
}
#[switchy_async::test]
async fn test_complex_breakpoint_demonstration() {
demonstrate_complex_breakpoint_patterns().await.unwrap();
}
}