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 {}