lariv-rs 0.1.0

Compile-time plugin web application framework built on Axum, SeaORM, Maud, and HTMX
Documentation
use sea_orm::Statement;
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

const ADD_ADDRESS_LINE_1: &str =
    "ALTER TABLE customers ADD COLUMN IF NOT EXISTS address_line_1 TEXT";
const ADD_ADDRESS_LINE_2: &str =
    "ALTER TABLE customers ADD COLUMN IF NOT EXISTS address_line_2 TEXT";
const ADD_CITY: &str = "ALTER TABLE customers ADD COLUMN IF NOT EXISTS city TEXT";
const ADD_PINCODE: &str = "ALTER TABLE customers ADD COLUMN IF NOT EXISTS pincode TEXT";
const ADD_STATE: &str = "ALTER TABLE customers ADD COLUMN IF NOT EXISTS state TEXT";

const MIGRATE_AND_DROP_ADDRESS: &str = r#"
DO $$
BEGIN
  IF EXISTS (
    SELECT 1 FROM information_schema.columns
    WHERE table_name = 'customers' AND column_name = 'address'
  ) THEN
    UPDATE customers
    SET address_line_1 = address
    WHERE address IS NOT NULL AND btrim(address) <> '';
    ALTER TABLE customers DROP COLUMN address;
  END IF;
END;
$$;
"#;

const ADD_ADDRESS: &str = "ALTER TABLE customers ADD COLUMN IF NOT EXISTS address TEXT";

const MERGE_ADDRESS_FIELDS: &str = r#"
UPDATE customers
SET address = NULLIF(
  concat_ws(
    E'\n',
    NULLIF(btrim(address_line_1), ''),
    NULLIF(btrim(address_line_2), ''),
    NULLIF(btrim(city), ''),
    NULLIF(btrim(pincode), ''),
    NULLIF(btrim(state), '')
  ),
  ''
)
"#;

const DROP_ADDRESS_LINE_1: &str = "ALTER TABLE customers DROP COLUMN IF EXISTS address_line_1";
const DROP_ADDRESS_LINE_2: &str = "ALTER TABLE customers DROP COLUMN IF EXISTS address_line_2";
const DROP_CITY: &str = "ALTER TABLE customers DROP COLUMN IF EXISTS city";
const DROP_PINCODE: &str = "ALTER TABLE customers DROP COLUMN IF EXISTS pincode";
const DROP_STATE: &str = "ALTER TABLE customers DROP COLUMN IF EXISTS state";

async fn execute(manager: &SchemaManager<'_>, sql: &str) -> Result<(), DbErr> {
    manager
        .get_connection()
        .execute(Statement::from_string(
            manager.get_connection().get_database_backend(),
            sql.to_string(),
        ))
        .await
        .map(|_| ())
}

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        execute(manager, ADD_ADDRESS_LINE_1).await?;
        execute(manager, ADD_ADDRESS_LINE_2).await?;
        execute(manager, ADD_CITY).await?;
        execute(manager, ADD_PINCODE).await?;
        execute(manager, ADD_STATE).await?;
        execute(manager, MIGRATE_AND_DROP_ADDRESS).await
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        execute(manager, ADD_ADDRESS).await?;
        execute(manager, MERGE_ADDRESS_FIELDS).await?;
        execute(manager, DROP_ADDRESS_LINE_1).await?;
        execute(manager, DROP_ADDRESS_LINE_2).await?;
        execute(manager, DROP_CITY).await?;
        execute(manager, DROP_PINCODE).await?;
        execute(manager, DROP_STATE).await
    }
}