use crate::query::expr::Expr;
#[derive(Debug, Clone)]
pub enum SelectItem {
Column {
table: &'static str,
column: &'static str,
},
Expression(Expr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JoinKind {
Inner,
Left,
Right,
Full,
Cross,
}
impl JoinKind {
pub fn as_sql(self) -> &'static str {
match self {
JoinKind::Inner => "INNER JOIN",
JoinKind::Left => "LEFT JOIN",
JoinKind::Right => "RIGHT JOIN",
JoinKind::Full => "FULL OUTER JOIN",
JoinKind::Cross => "CROSS JOIN",
}
}
}
#[derive(Debug, Clone)]
pub struct Join {
pub kind: JoinKind,
pub table: &'static str,
pub alias: Option<&'static str>,
pub left_table: &'static str,
pub left_column: &'static str,
pub right_table: &'static str,
pub right_column: &'static str,
}
#[derive(Debug, Clone)]
pub struct OrderTerm {
pub expr: Expr,
pub descending: bool,
pub nulls: Option<bool>,
}
impl OrderTerm {
pub fn new(expr: Expr, descending: bool) -> Self {
Self { expr, descending, nulls: None }
}
pub fn nulls_first(mut self) -> Self {
self.nulls = Some(true);
self
}
pub fn nulls_last(mut self) -> Self {
self.nulls = Some(false);
self
}
}
#[derive(Debug, Clone)]
pub struct Cte {
pub name: &'static str,
pub columns: Option<Vec<&'static str>>,
pub query: CteQuery,
}
#[derive(Debug, Clone)]
pub enum CteQuery {
Select(SelectStatement),
Union(Box<UnionStatement>),
}
#[derive(Debug, Clone)]
pub struct WithClause {
pub recursive: bool,
pub ctes: Vec<Cte>,
}
#[derive(Debug, Clone)]
pub struct SelectStatement {
pub with: Option<WithClause>,
pub table: &'static str,
pub projection: Vec<SelectItem>,
pub joins: Vec<Join>,
pub filters: Vec<Expr>,
pub group_by: Vec<Expr>,
pub having: Option<Expr>,
pub order_by: Vec<OrderTerm>,
pub limit: Option<u64>,
pub offset: Option<u64>,
pub distinct: bool,
pub distinct_on: Vec<Expr>,
pub lock: Option<LockClause>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LockStrength {
Update,
Share,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LockWait {
Wait,
NoWait,
SkipLocked,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LockClause {
pub strength: LockStrength,
pub wait: LockWait,
pub of: Vec<&'static str>,
}
impl LockClause {
pub fn new(strength: LockStrength) -> Self {
Self { strength, wait: LockWait::Wait, of: Vec::new() }
}
pub fn uses_modifiers(&self) -> bool {
self.strength != LockStrength::Update
|| self.wait != LockWait::Wait
|| !self.of.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct UnionStatement {
pub first: SelectStatement,
pub rest: Vec<(bool, SelectStatement)>,
pub order_by: Vec<OrderTerm>,
pub limit: Option<u64>,
pub offset: Option<u64>,
pub lock: Option<LockClause>,
}
impl SelectStatement {
pub fn new(table: &'static str, projection: Vec<SelectItem>) -> Self {
Self {
with: None,
table,
projection,
joins: Vec::new(),
filters: Vec::new(),
group_by: Vec::new(),
having: None,
order_by: Vec::new(),
limit: None,
offset: None,
distinct: false,
distinct_on: Vec::new(),
lock: None,
}
}
}