sqlstr 0.1.0

Sql string builder
Documentation
use core::marker::PhantomData;

use crate::WriteSql;

pub struct Group<'cmd, Sql: WriteSql<Arg>, Arg>(&'cmd mut Sql, PhantomData<Arg>);

impl<'cmd, Sql, Arg> Group<'cmd, Sql, Arg>
where
    Sql: WriteSql<Arg>,
{
    pub fn open(command: &'cmd mut Sql) -> Self {
        command.push_cmd("(");
        Self(command, PhantomData)
    }

    pub fn close(self) {
        core::mem::drop(self)
    }

    pub fn sql(&mut self) -> &mut Sql {
        self.0
    }
}

impl<'cmd, Sql, Arg> WriteSql<Arg> for Group<'cmd, Sql, Arg>
where
    Sql: WriteSql<Arg>,
{
    fn push_expr<T>(&mut self, operand: crate::SqlExpr<'_, T>) -> Result<(), <Arg>::Error>
    where
        Arg: crate::ArgumentBuffer<T>,
    {
        self.0.push_expr(operand)
    }

    fn push_value<T>(&mut self, value: T) -> Result<(), <Arg>::Error>
    where
        Arg: crate::ArgumentBuffer<T>,
    {
        self.0.push_value(value)
    }

    fn push_cmd(&mut self, expr: &str) {
        self.0.push_cmd(expr)
    }

    fn as_command(&self) -> &str {
        self.0.as_command()
    }
}

impl<'cmd, Sql, Arg> Drop for Group<'cmd, Sql, Arg>
where
    Sql: WriteSql<Arg>,
{
    fn drop(&mut self) {
        self.0.push_cmd(")");
    }
}

#[cfg(test)]
mod test {
    use alloc::string::String;

    use super::Group;
    use crate::{test::TestArgs, SqlCommand};

    #[test]
    fn group_condition() {
        let mut sql = SqlCommand::new(String::new(), TestArgs::new());
        let mut group = Group::open(&mut sql);
        group.sql().push_cmd("user.name = ");
        group.sql().push_value("Rust").unwrap();
        group.sql().push_cmd(" AND user.active = ");
        group.sql().push_value(true).unwrap();
        group.close();

        assert_eq!(sql.as_command(), "(user.name = $1 AND user.active = $2)");
        assert_eq!(sql.arguments.as_str(), "Rust;true;");
    }

    #[test]
    fn group_scope() {
        let mut sql: SqlCommand<TestArgs> = SqlCommand::default();
        {
            let mut group = Group::open(&mut sql);
            group.sql().push_cmd("user.name = ");
            group.sql().push_value("Rust").unwrap();
            group.sql().push_cmd(" AND user.active = ");
            group.sql().push_value(true).unwrap();
        }

        assert_eq!(sql.as_command(), "(user.name = $1 AND user.active = $2)");
        assert_eq!(sql.arguments.as_str(), "Rust;true;");
    }
}