sqlgen 0.1.6

A library to generate SQL Statements.
Documentation
use crate::{
    common::SqlGenError,
    main_parts::{from::From, r#where::Where, select::Select},
    sub_parts::{select_list::SelectList, table_source::TableSource},
};

use crate::prelude::*;

#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug)]
pub struct SelectQuery {
    context: Context,
    select: Select,
    from: From,
    r#where: Option<Where>,
}

impl SelectQuery {
    pub fn new() -> SelectQueryBuilder {
        SelectQueryBuilder {
            select: None,
            from: None,
            r#where: None,
        }
    }

    pub fn sql(self) -> Result<String> {
        let s = String::new();

        let s = self.select.sql(s, &self.context)?;
        let mut s = self.from.sql(s, &self.context)?;
        if let Some(r#where) = self.r#where {
            s = r#where.sql(s, &self.context)?;
        }

        Ok(s)
    }
}

#[derive(Debug)]
pub struct SelectQueryBuilder {
    select: Option<Select>,
    from: Option<From>,
    r#where: Option<Where>,
}

impl SelectQueryBuilder {
    pub fn select(mut self, select_list: impl Into<SelectList>) -> Result<Self> {
        let select_list = select_list.into();
        match &mut self.select {
            Some(select) => select.push(select_list),
            None => {
                let mut select = Select::new();
                select.push(select_list);
                self.select = Some(select);
            }
        }

        Ok(self)
    }

    pub fn from(self, table_source: impl Into<TableSource>) -> Result<Self> {
        let table_source = table_source.into();

        self.push_from(table_source)
    }

    pub(crate) fn push_from(mut self, table_source: TableSource) -> Result<Self> {
        match &mut self.from {
            Some(from) => from.push(table_source),
            None => {
                let mut from = From::new();
                from.push(table_source);

                self.from = Some(from);
            }
        }

        Ok(self)
    }

    pub fn r#where(mut self, search_condition: impl Into<SearchCondition>) -> Result<Self> {
        self.r#where = Some(Where::new(search_condition.into()));
        Ok(self)
    }

    pub fn join(self, table_source: TableSource) -> Result<Self> {
        self.push_from(table_source)
    }

    pub fn inner_join(
        self,
        table_source: impl Into<TableSource>,
    ) -> Result<JoinTableSourceBuilder> {
        let table_source: TableSource = table_source.into();
        let builder = JoinTableSourceBuilder::join(JoinType::Inner, self, table_source);

        Ok(builder)
    }

    pub fn left_join(self, table_source: impl Into<TableSource>) -> Result<JoinTableSourceBuilder> {
        let table_source: TableSource = table_source.into();
        let builder = JoinTableSourceBuilder::join(JoinType::Left, self, table_source);

        Ok(builder)
    }

    pub fn right_join(
        self,
        table_source: impl Into<TableSource>,
    ) -> Result<JoinTableSourceBuilder> {
        let table_source: TableSource = table_source.into();
        let builder = JoinTableSourceBuilder::join(JoinType::Right, self, table_source);

        Ok(builder)
    }

    pub fn full_join(self, table_source: impl Into<TableSource>) -> Result<JoinTableSourceBuilder> {
        let table_source: TableSource = table_source.into();
        let builder = JoinTableSourceBuilder::join(JoinType::Full, self, table_source);

        Ok(builder)
    }

    pub fn query(self) -> Result<SelectQuery> {
        let select_query = match (self.select, self.from) {
            (Some(select), Some(from)) => Ok(SelectQuery {
                context: Context::new(),
                select,
                from,
                r#where: self.r#where,
            }),
            _ => Err(SqlGenError::MissingParts(
                "At least Select and From is needed for a query".into(),
            )),
        };

        select_query
    }

    pub fn sql(self) -> Result<String> {
        let query = self.query()?;
        query.sql()
    }
}

#[cfg(test)]
mod tests {}