pg-setup 0.2.0

Helper to create and drop postgres DBs. Useful for testing.
Documentation
use crate::error::Result;

pub struct TableBuilder {
    table_name: String,
    columns: Vec<Column>,
}

impl TableBuilder {
    pub fn new(table_name: impl ToString) -> TableBuilder {
        TableBuilder {
            table_name: table_name.to_string(),
            columns: Vec::new(),
        }
    }

    pub fn add_column<F>(
        &mut self,
        name: impl ToString,
        col_type: impl ToString,
        col_configurator: F,
    ) where
        F: FnOnce(&mut Column),
    {
        let mut col = Column {
            name: name.to_string(),
            col_type: col_type.to_string(),
            constraints: Default::default(),
        };
        col_configurator(&mut col);
        self.columns.push(col);
    }

    pub fn to_sql(&self) -> Result<String> {
        let mut sql = String::new();
        sql.push_str("CREATE TABLE IF NOT EXISTS ");
        sql.push_str(&self.table_name);
        sql.push_str(" (");
        for (i, col) in self.columns.iter().enumerate() {
            if i > 0 {
                sql.push_str(", ");
            }
            sql.push_str(&col.to_sql()?);
        }
        sql.push_str(");");
        Ok(sql)
    }
}

pub struct Column {
    name: String,
    col_type: String,
    constraints: Vec<String>,
}

impl Column {
    pub fn add_constraint(&mut self, constraint: impl ToString) {
        self.constraints.push(constraint.to_string());
    }

    pub fn primary_key(&mut self) {
        self.add_constraint("PRIMARY KEY");
    }

    pub fn not_null(&mut self) {
        self.add_constraint("NOT NULL");
    }

    pub fn unique(&mut self) {
        self.add_constraint("UNIQUE");
    }

    pub fn default(&mut self, default: impl ToString) {
        self.add_constraint(format!("DEFAULT {}", default.to_string()));
    }

    pub fn check(&mut self, check: impl ToString) {
        self.add_constraint(format!("CHECK ({})", check.to_string()));
    }

    pub fn references(&mut self, table: impl ToString, column: impl ToString) {
        self.add_constraint(format!(
            "REFERENCES {} ({})",
            table.to_string(),
            column.to_string()
        ));
    }

    pub fn foreign_key(&mut self, table: impl ToString, column: impl ToString) {
        self.references(table, column);
        self.add_constraint("FOREIGN KEY");
    }

    fn to_sql(&self) -> Result<String> {
        Ok(self.to_string())
    }
}

impl std::fmt::Display for Column {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} {}", self.name, self.col_type)?;
        for constraint in &self.constraints {
            write!(f, " {}", constraint)?;
        }
        Ok(())
    }
}