3 releases

0.1.2 Dec 13, 2023
0.1.1 Jun 9, 2023
0.1.0 Jun 6, 2023

#2694 in Database interfaces

Download history 3/week @ 2024-08-18 7/week @ 2024-08-25 11/week @ 2024-09-01 9/week @ 2024-09-08 28/week @ 2024-09-15 22/week @ 2024-09-22 8/week @ 2024-09-29 14/week @ 2024-10-06 1/week @ 2024-10-13 40/week @ 2024-10-20 27/week @ 2024-10-27 36/week @ 2024-11-03 28/week @ 2024-11-10 19/week @ 2024-11-17 14/week @ 2024-11-24 78/week @ 2024-12-01

139 downloads per month

Apache-2.0

1.5MB
729 lines

Promad

Migration tool for SQLx that allows for arbitrary SQL/Rust execution within a transaction on the write connection.

Features

  • Rust code mixed with SQL in migrations.
  • Scan migrations across a table with blob data using Rust.
  • Embeddable CLI.

Example

# #[tokio::main]
# async fn main() {
use std::borrow::Cow;
use async_trait::async_trait;
use promad::{file_basename, Migration, Migrator, error::{Error, Result}};
use sqlx::{postgres::PgPoolOptions, PgPool, Postgres, Executor, Row};
use testcontainers::{clients, Container};

pub struct FirstMigration;

#[async_trait]
impl Migration<Postgres> for FirstMigration {
    fn name(&self) -> &'static str {
        file_basename!()
    }

    async fn up(
        &self,
        _read: &mut sqlx::PgConnection,
        write: &mut sqlx::PgConnection,
    ) -> Result<()> {
        sqlx::query("CREATE TABLE test (id INT PRIMARY KEY)")
            .execute(write)
            .await?;
        Ok(())
    }

    async fn down(
        &self,
        _read: &mut sqlx::PgConnection,
        write: &mut sqlx::PgConnection,
    ) -> Result<()> {
        sqlx::query("DROP TABLE test")
            .execute(write)
            .await?;
        Ok(())
    }
}

let docker = clients::Cli::default();
let pgsql = docker.run(testcontainers::images::postgres::Postgres::default());
let port = pgsql.get_host_port_ipv4(5432);
let pool = PgPoolOptions::new()
    .connect(&format!(
        "postgres://postgres:postgres@localhost:{}/postgres",
        port
    ))
    .await.unwrap();

let mut migrator = Migrator::create(pool.clone());
migrator.add_migration(Box::new(FirstMigration));
migrator.apply_all().await.unwrap();

// Check that the table exists.
let mut conn = pool.acquire().await.unwrap();

let row = sqlx::query("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'test')")
    .fetch_one(conn.as_mut())
    .await.unwrap();

assert!(row.get::<bool, _>(0));

migrator.revert_all().await.unwrap();

let row = sqlx::query("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'test')")
    .fetch_one(conn.as_mut())
    .await.unwrap();

assert!(!row.get::<bool, _>(0));

# }

Dependencies

~54MB
~1M SLoC