ostring_sqlx 2.0.3

A basic configuration persistence wrapper
Documentation
use anyhow::{anyhow, Result};
use sqlx::sqlite::Sqlite;
use sqlx::{query, query_as, query_scalar, Pool};

#[derive(Debug, Clone, Default, sqlx::FromRow)]
pub struct UconfOption {
    pub user_id: Option<i32>,
    pub conf_id: Option<i32>,
    pub version: Option<String>,
    pub content: Option<String>,
}

#[derive(Debug, Clone)]
pub struct UconfQB {
    pool: Pool<Sqlite>,
    parm: UconfOption,
}

impl UconfQB {
    pub fn new(pool: Pool<Sqlite>) -> Self {
        UconfQB {
            pool,
            parm: UconfOption::default(),
        }
    }

    pub fn set_parm(mut self, parm: UconfOption) -> Self {
        self.parm = parm;
        self
    }

    pub async fn init_table(self) -> Result<Self> {
        query(
            r#"CREATE TABLE IF NOT EXISTS user_confs (
                    user_id INTEGER NOT NULL, 
                    conf_id INTEGER NOT NULL, 
                    version TEXT NOT NULL, 
                    content TEXT NOT NULL, 
                    PRIMARY KEY (user_id, conf_id, version))
                "#,
        )
        .execute(&self.pool.clone())
        .await?;
        Ok(self)
    }

    pub async fn get_all(&self) -> Result<Vec<UconfOption>> {
        let parm = self.parm.clone();
        parm.user_id.as_ref().ok_or(anyhow!("user_id is None"))?;
        parm.conf_id.as_ref().ok_or(anyhow!("conf_id is None"))?;

        let confs: Vec<UconfOption> =
            query_as("SELECT * FROM user_confs WHERE user_id = ? AND conf_id = ?")
                .bind(parm.user_id)
                .bind(parm.conf_id)
                .fetch_all(&self.pool.clone())
                .await?;
        return Ok(confs);
    }

    pub async fn read(&self) -> Result<Option<String>> {
        let parm = self.parm.clone();
        parm.user_id.as_ref().ok_or(anyhow!("user_id is None"))?;
        parm.conf_id.as_ref().ok_or(anyhow!("conf_id is None"))?;
        parm.version.as_ref().ok_or(anyhow!("version is None"))?;

        let content = query_scalar(
            "SELECT content FROM user_confs WHERE user_id = ? AND conf_id = ? AND version = ?",
        )
        .bind(parm.user_id)
        .bind(parm.conf_id)
        .bind(parm.version)
        .fetch_optional(&self.pool.clone())
        .await?;
        return Ok(content);
    }

    pub async fn save(self) -> Result<Self> {
        let parm = self.parm.clone();
        parm.user_id.as_ref().ok_or(anyhow!("user_id is None"))?;
        parm.conf_id.as_ref().ok_or(anyhow!("conf_id is None"))?;
        parm.version.as_ref().ok_or(anyhow!("version is None"))?;
        parm.content.as_ref().ok_or(anyhow!("content is None"))?;

        let query_str = match self.read().await? {
            Some(_) => "UPDATE user_confs SET content = $4 WHERE user_id = $1 AND conf_id = $2 AND version = $3",
            None => "INSERT INTO user_confs (user_id, conf_id, version, content) VALUES ($1, $2, $3, $4)"
        };
        query(query_str)
            .bind(parm.user_id)
            .bind(parm.conf_id)
            .bind(parm.version)
            .bind(parm.content)
            .execute(&self.pool.clone())
            .await?;
        return Ok(self);
    }

    pub async fn remove(self) -> Result<()> {
        let parm = self.parm.clone();
        parm.user_id.as_ref().ok_or(anyhow!("user_id is None"))?;
        parm.conf_id.as_ref().ok_or(anyhow!("conf_id is None"))?;
        parm.version.as_ref().ok_or(anyhow!("version is None"))?;
        query("DELETE FROM user_confs WHERE user_id = ? AND conf_id = ? AND version = ?")
            .bind(parm.user_id)
            .bind(parm.conf_id)
            .bind(parm.version)
            .execute(&self.pool.clone())
            .await?;
        Ok(())
    }
}