sql_query 0.0.0

composible sql query builder, with support of binding into query buffer
Documentation
use std::marker::PhantomData;

use sqlx::Database;

use crate::{
    returning::ReturningClause,
    select_st::{HandleAccept, HandleAcceptIsWorking},
    Accept, Query, SupportNamedBind, WhereItem,
};

pub struct UpdateSt<S, Q: Query<S>, R = ()> {
    pub(crate) sets: Vec<(&'static str, Q::SqlPart)>,
    pub(crate) where_clause: Vec<Q::SqlPart>,
    pub(crate) ctx: Q::Context1,
    pub(crate) table: &'static str,
    pub(crate) returning: R,
    pub(crate) _sqlx: PhantomData<S>,
}

impl<'q, S, R, Q> UpdateSt<S, Q, R>
where
    S: SupportNamedBind,
    S: Database,
    Q: Query<S>,
{
    pub fn _build(self) -> (String, Q::Output)
    where
        R: ReturningClause,
        S: Database + SupportNamedBind,
    {
        <Q as Query<S>>::build_query(self.ctx, |ctx| {
            let mut str = String::from("UPDATE ");

            str.push_str(self.table);

            str.push_str(" SET ");

            if self.sets.is_empty() {
                panic!("empty set on update")
            }

            for (index, (column, value)) in
                self.sets.into_iter().enumerate()
            {
                if index != 0 {
                    str.push_str(", ");
                }
                str.push_str(column);
                str.push_str(" = ");
                str.push_str(
                    &<Q as Query<S>>::build_sql_part_back(
                        ctx, value,
                    ),
                );
            }

            for (index, where_item) in
                self.where_clause.into_iter().enumerate()
            {
                if index == 0 {
                    str.push_str(" WHERE ");
                } else {
                    str.push_str(" AND ");
                }
                str.push_str(
                    &<Q as Query<S>>::build_sql_part_back(
                        ctx, where_item,
                    ),
                );
            }

            str.push_str(&self.returning.returning());

            str
        })
    }
}

impl<S, Q: Query<S>> UpdateSt<S, Q, ()> {
    pub fn returning(
        self,
        cols: Vec<&'static str>,
    ) -> UpdateSt<S, Q, Vec<&'static str>> {
        UpdateSt {
            sets: self.sets,
            where_clause: self.where_clause,
            ctx: self.ctx,
            table: self.table,
            returning: cols,
            _sqlx: PhantomData,
        }
    }
}
impl<S, Q: Query<S>, R> UpdateSt<S, Q, R> {
    pub fn set<T>(&mut self, column: &'static str, value: T)
    where
        Q: Accept<T, S>,
        HandleAccept<T, S, Q>: HandleAcceptIsWorking<
            SqlPart = Q::SqlPart,
            Ctx = Q::Context1,
        >,
    {
        let part = HandleAccept(value, PhantomData)
            .to_sql_part(&mut self.ctx);
        self.sets.push((column, part));
    }

    pub fn where_(
        &mut self,
        item: impl WhereItem<S, Q> + 'static,
    ) {
        let item = Q::handle_where_item(item, &mut self.ctx);
        self.where_clause.push(item);
    }
}