use crate::{Distinct, Query, Sql};
#[derive(Clone)]
pub enum SelectExpression<'a> {
Column(&'a str),
Subquery(Box<Query<'a>>, Option<&'a str>),
}
impl<'a> Sql for SelectExpression<'a> {
fn sql(&self) -> String {
match self {
SelectExpression::Column(col) => col.to_string(),
SelectExpression::Subquery(query, alias) => {
if let Some(a) = alias {
format!("({}) AS {}", query.sql(), a)
} else {
format!("({})", query.sql())
}
}
}
}
}
#[derive(Clone)]
pub enum Columns<'a> {
Star,
Selected(Vec<&'a str>),
Expressions(Vec<SelectExpression<'a>>),
}
impl<'a> Sql for Columns<'a> {
fn sql(&self) -> String {
match &self {
Columns::Star => "*".to_string(),
Columns::Selected(v) => v.join(", ").to_string(),
Columns::Expressions(exprs) => exprs
.iter()
.map(|e| e.sql())
.collect::<Vec<String>>()
.join(", "),
}
}
}
#[derive(Clone)]
pub struct Select<'a> {
pub cols: Columns<'a>,
pub distinct: Option<Distinct<'a>>,
}
impl<'a> Select<'a> {
pub fn new(c: Columns<'a>, d: Option<Distinct<'a>>) -> Select<'a> {
Select {
cols: c,
distinct: d,
}
}
}
impl<'a> Sql for Select<'a> {
fn sql(&self) -> String {
let mut s = String::new();
if let Some(d) = &self.distinct {
match d {
Distinct::All => s.push_str("DISTINCT "),
Distinct::On(cols) => s.push_str(&format!("DISTINCT ON ({}) ", cols.join(", "))),
}
}
s.push_str(&self.cols.sql());
s
}
}