migration.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. use refinery::embed_migrations;
  2. use tokio_postgres::Client;
  3. embed_migrations!("./src/supabase/migrations");
  4. const AF_MIGRATION_HISTORY: &str = "af_migration_history";
  5. pub(crate) async fn run_migrations(client: &mut Client) -> Result<(), anyhow::Error> {
  6. match migrations::runner()
  7. .set_migration_table_name(AF_MIGRATION_HISTORY)
  8. .run_async(client)
  9. .await
  10. {
  11. Ok(report) => {
  12. if !report.applied_migrations().is_empty() {
  13. tracing::info!("Run postgres db migration: {:?}", report);
  14. }
  15. Ok(())
  16. },
  17. Err(e) => {
  18. tracing::error!("postgres db migration error: {}", e);
  19. Err(anyhow::anyhow!("postgres db migration error: {}", e))
  20. },
  21. }
  22. }
  23. /// Drop all tables and dependencies defined in the v1_initial_up.sql.
  24. /// Be careful when using this function. It will drop all tables and dependencies.
  25. /// Mostly used for testing.
  26. #[allow(dead_code)]
  27. #[cfg(debug_assertions)]
  28. pub(crate) async fn run_initial_drop(client: &Client) {
  29. // let sql = include_str!("migrations/initial/initial_down.sql");
  30. let sql = r#"DROP TABLE IF EXISTS af_user;
  31. DROP TABLE IF EXISTS af_workspace;
  32. DROP TABLE IF EXISTS af_user_profile;
  33. DROP TABLE IF EXISTS af_collab;
  34. DROP VIEW IF EXISTS af_collab_state;
  35. DROP TABLE IF EXISTS af_collab_snapshot;
  36. DROP TABLE IF EXISTS af_collab_statistics;
  37. DROP TRIGGER IF EXISTS create_af_user_profile_trigger ON af_user_profile CASCADE;
  38. DROP FUNCTION IF EXISTS create_af_user_profile_trigger_func;
  39. DROP TRIGGER IF EXISTS create_af_workspace_trigger ON af_workspace CASCADE;
  40. DROP FUNCTION IF EXISTS create_af_workspace_trigger_func;
  41. DROP TRIGGER IF EXISTS af_collab_insert_trigger ON af_collab CASCADE;
  42. DROP FUNCTION IF EXISTS increment_af_collab_update_count;
  43. DROP TRIGGER IF EXISTS af_collab_snapshot_update_edit_count_trigger ON af_collab_snapshot;
  44. DROP FUNCTION IF EXISTS af_collab_snapshot_update_edit_count;
  45. DROP TRIGGER IF EXISTS check_and_delete_snapshots_trigger ON af_collab_snapshot CASCADE;
  46. DROP FUNCTION IF EXISTS check_and_delete_snapshots;
  47. "#;
  48. client.batch_execute(sql).await.unwrap();
  49. client
  50. .batch_execute("DROP TABLE IF EXISTS af_migration_history")
  51. .await
  52. .unwrap();
  53. }
  54. #[cfg(test)]
  55. mod tests {
  56. use tokio_postgres::NoTls;
  57. use crate::supabase::migration::run_initial_drop;
  58. use crate::supabase::*;
  59. // ‼️‼️‼️ Warning: this test will create a table in the database
  60. #[tokio::test]
  61. async fn test_postgres_db() -> Result<(), anyhow::Error> {
  62. if dotenv::from_filename(".env.test.danger").is_err() {
  63. return Ok(());
  64. }
  65. let configuration = PostgresConfiguration::from_env().unwrap();
  66. let mut config = tokio_postgres::Config::new();
  67. config
  68. .host(&configuration.url)
  69. .user(&configuration.user_name)
  70. .password(&configuration.password)
  71. .port(configuration.port);
  72. // Using the https://docs.rs/postgres-openssl/latest/postgres_openssl/ to enable tls connection.
  73. let (client, connection) = config.connect(NoTls).await?;
  74. tokio::spawn(async move {
  75. if let Err(e) = connection.await {
  76. tracing::error!("postgres db connection error: {}", e);
  77. }
  78. });
  79. #[cfg(debug_assertions)]
  80. {
  81. run_initial_drop(&client).await;
  82. }
  83. Ok(())
  84. }
  85. }