sqlcx-core 0.2.1

SQL-first cross-language type-safe code generator — core library
Documentation
use crate::error::{Result, SqlcxError};
use crate::migrate::driver::MigrationDriver;
use crate::migrate::file::MigrationFile;
use crate::migrate::state::{
    AppliedMigration, CREATE_STATE_TABLE_SQL, INSERT_APPLIED_SQL, SELECT_APPLIED_SQL,
};
use postgres::{Client, NoTls};

pub struct PostgresDriver {
    client: Client,
}

impl PostgresDriver {
    pub fn connect(database_url: &str) -> Result<Self> {
        let client = Client::connect(database_url, NoTls)
            .map_err(|e| SqlcxError::Migrate(format!("connection failed: {e}")))?;
        Ok(Self { client })
    }
}

impl MigrationDriver for PostgresDriver {
    fn ensure_state_table(&mut self) -> Result<()> {
        self.client
            .batch_execute(CREATE_STATE_TABLE_SQL)
            .map_err(|e| SqlcxError::Migrate(format!("ensure_state_table: {e}")))?;
        Ok(())
    }

    fn list_applied(&mut self) -> Result<Vec<AppliedMigration>> {
        let rows = self
            .client
            .query(SELECT_APPLIED_SQL, &[])
            .map_err(|e| SqlcxError::Migrate(format!("list_applied: {e}")))?;
        let mut out = Vec::with_capacity(rows.len());
        for row in rows {
            out.push(AppliedMigration {
                version: row.get(0),
                name: row.get(1),
                checksum: row.get(2),
            });
        }
        Ok(out)
    }

    fn apply_migration(&mut self, file: &MigrationFile) -> Result<()> {
        let mut tx = self
            .client
            .transaction()
            .map_err(|e| SqlcxError::Migrate(format!("begin tx: {e}")))?;
        tx.batch_execute(&file.content)
            .map_err(|e| SqlcxError::Migrate(format!("{}: {e}", file.version)))?;
        tx.execute(
            INSERT_APPLIED_SQL,
            &[&file.version, &file.name, &file.checksum],
        )
        .map_err(|e| SqlcxError::Migrate(format!("record state {}: {e}", file.version)))?;
        tx.commit()
            .map_err(|e| SqlcxError::Migrate(format!("commit {}: {e}", file.version)))?;
        Ok(())
    }
}