db.rs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. use anyhow::Context as _;
  2. pub use tokio_postgres::Client as DbClient;
  3. pub mod notifications;
  4. pub async fn run_migrations(client: &DbClient) -> anyhow::Result<()> {
  5. client
  6. .execute(
  7. "CREATE TABLE IF NOT EXISTS database_versions (
  8. zero INTEGER PRIMARY KEY,
  9. migration_counter INTEGER
  10. );",
  11. &[],
  12. )
  13. .await
  14. .context("creating database versioning table")?;
  15. client
  16. .execute(
  17. "INSERT INTO database_versions (zero, migration_counter)
  18. VALUES (0, 0)
  19. ON CONFLICT DO NOTHING",
  20. &[],
  21. )
  22. .await
  23. .context("inserting initial database_versions")?;
  24. let migration_idx: i32 = client
  25. .query_one("SELECT migration_counter FROM database_versions", &[])
  26. .await
  27. .context("getting migration counter")?
  28. .get(0);
  29. let migration_idx = migration_idx as usize;
  30. for (idx, migration) in MIGRATIONS.iter().enumerate() {
  31. if idx >= migration_idx {
  32. client
  33. .execute(*migration, &[])
  34. .await
  35. .with_context(|| format!("executing {}th migration", idx))?;
  36. client
  37. .execute(
  38. "UPDATE database_versions SET migration_counter = $1",
  39. &[&(idx as i32 + 1)],
  40. )
  41. .await
  42. .with_context(|| format!("updating migration counter to {}", idx))?;
  43. }
  44. }
  45. Ok(())
  46. }
  47. static MIGRATIONS: &[&str] = &[
  48. "
  49. CREATE TABLE notifications (
  50. notification_id BIGSERIAL PRIMARY KEY,
  51. user_id BIGINT,
  52. origin_url TEXT NOT NULL,
  53. origin_html TEXT,
  54. time TIMESTAMP WITH TIME ZONE
  55. );
  56. ",
  57. "
  58. CREATE TABLE users (
  59. user_id BIGINT PRIMARY KEY,
  60. username TEXT NOT NULL
  61. );
  62. ",
  63. "ALTER TABLE notifications ADD COLUMN short_description TEXT;",
  64. "ALTER TABLE notifications ADD COLUMN team_name TEXT;",
  65. ];