use crate::expr::Expr;
use crate::{ColumnName, PgType, TableName};
#[derive(Debug, Clone)]
pub enum Stmt {
Select(SelectStmt),
Insert(InsertStmt),
InsertSelect(InsertSelectStmt),
Update(UpdateStmt),
Delete(DeleteStmt),
}
#[derive(Debug, Clone, Default)]
pub struct SelectStmt {
pub distinct: bool,
pub distinct_on: Vec<Expr>,
pub columns: Vec<SelectColumn>,
pub from: Option<FromClause>,
pub joins: Vec<Join>,
pub where_: Option<Expr>,
pub order_by: Vec<OrderBy>,
pub limit: Option<Expr>,
pub offset: Option<Expr>,
}
#[derive(Debug, Clone)]
pub enum SelectColumn {
Expr {
expr: Expr,
alias: Option<ColumnName>,
},
AllFrom(TableName),
}
impl SelectColumn {
pub fn expr(expr: Expr) -> Self {
SelectColumn::Expr { expr, alias: None }
}
pub fn aliased(expr: Expr, alias: ColumnName) -> Self {
SelectColumn::Expr {
expr,
alias: Some(alias),
}
}
pub fn all_from(table: TableName) -> Self {
SelectColumn::AllFrom(table)
}
}
#[derive(Debug, Clone)]
pub struct FromClause {
pub table: TableName,
pub alias: Option<TableName>,
}
impl FromClause {
pub fn table(name: TableName) -> Self {
Self {
table: name,
alias: None,
}
}
pub fn aliased(name: TableName, alias: TableName) -> Self {
Self {
table: name,
alias: Some(alias),
}
}
}
#[derive(Debug, Clone)]
pub struct Unnest {
pub params: Vec<UnnestParam>,
pub alias: TableName,
}
#[derive(Debug, Clone)]
pub struct UnnestParam {
pub name: ColumnName,
pub pg_type: PgType,
}
impl UnnestParam {
pub fn new(name: ColumnName, pg_type: PgType) -> Self {
Self { name, pg_type }
}
}
impl Unnest {
pub fn new(alias: TableName) -> Self {
Self {
params: Vec::new(),
alias,
}
}
pub fn param(mut self, name: ColumnName, pg_type: PgType) -> Self {
self.params.push(UnnestParam::new(name, pg_type));
self
}
pub fn params(mut self, params: impl IntoIterator<Item = UnnestParam>) -> Self {
self.params.extend(params);
self
}
}
#[derive(Debug, Clone)]
pub struct Join {
pub kind: JoinKind,
pub table: TableName,
pub alias: Option<TableName>,
pub on: Expr,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JoinKind {
Inner,
Left,
Right,
Full,
}
impl JoinKind {
pub fn as_str(self) -> &'static str {
match self {
JoinKind::Inner => "INNER JOIN",
JoinKind::Left => "LEFT JOIN",
JoinKind::Right => "RIGHT JOIN",
JoinKind::Full => "FULL JOIN",
}
}
}
#[derive(Debug, Clone)]
pub struct OrderBy {
pub expr: Expr,
pub desc: bool,
pub nulls: Option<NullsOrder>,
}
impl OrderBy {
pub fn asc(expr: Expr) -> Self {
Self {
expr,
desc: false,
nulls: None,
}
}
pub fn desc(expr: Expr) -> Self {
Self {
expr,
desc: true,
nulls: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NullsOrder {
First,
Last,
}
#[derive(Debug, Clone)]
pub struct InsertStmt {
pub table: TableName,
pub columns: Vec<ColumnName>,
pub values: Vec<Expr>,
pub on_conflict: Option<OnConflict>,
pub returning: Vec<ColumnName>,
}
#[derive(Debug, Clone)]
pub struct OnConflict {
pub columns: Vec<ColumnName>,
pub action: ConflictAction,
}
#[derive(Debug, Clone)]
pub enum ConflictAction {
DoNothing,
DoUpdate(Vec<UpdateAssignment>),
}
#[derive(Debug, Clone)]
pub struct InsertSelectStmt {
pub table: TableName,
pub columns: Vec<ColumnName>,
pub select_exprs: Vec<Expr>,
pub unnest: Unnest,
pub on_conflict: Option<OnConflict>,
pub returning: Vec<ColumnName>,
}
#[derive(Debug, Clone)]
pub struct UpdateAssignment {
pub column: ColumnName,
pub value: Expr,
}
impl UpdateAssignment {
pub fn new(column: ColumnName, value: Expr) -> Self {
Self { column, value }
}
}
#[derive(Debug, Clone)]
pub struct UpdateStmt {
pub table: TableName,
pub assignments: Vec<UpdateAssignment>,
pub where_: Option<Expr>,
pub returning: Vec<ColumnName>,
}
#[derive(Debug, Clone)]
pub struct DeleteStmt {
pub table: TableName,
pub where_: Option<Expr>,
pub returning: Vec<ColumnName>,
}
impl SelectStmt {
pub fn new() -> Self {
Self::default()
}
pub fn distinct(mut self) -> Self {
self.distinct = true;
self
}
pub fn distinct_on(mut self, cols: impl IntoIterator<Item = Expr>) -> Self {
self.distinct_on.extend(cols);
self
}
pub fn column(mut self, col: SelectColumn) -> Self {
self.columns.push(col);
self
}
pub fn columns(mut self, cols: impl IntoIterator<Item = SelectColumn>) -> Self {
self.columns.extend(cols);
self
}
pub fn from(mut self, from: FromClause) -> Self {
self.from = Some(from);
self
}
pub fn join(mut self, join: Join) -> Self {
self.joins.push(join);
self
}
pub fn where_(mut self, expr: Expr) -> Self {
self.where_ = Some(expr);
self
}
pub fn and_where(mut self, expr: Expr) -> Self {
self.where_ = Some(match self.where_ {
Some(existing) => existing.and(expr),
None => expr,
});
self
}
pub fn order_by(mut self, order: OrderBy) -> Self {
self.order_by.push(order);
self
}
pub fn limit(mut self, expr: Expr) -> Self {
self.limit = Some(expr);
self
}
pub fn offset(mut self, expr: Expr) -> Self {
self.offset = Some(expr);
self
}
}
impl InsertStmt {
pub fn new(table: TableName) -> Self {
Self {
table,
columns: Vec::new(),
values: Vec::new(),
on_conflict: None,
returning: Vec::new(),
}
}
pub fn column(mut self, name: ColumnName, value: Expr) -> Self {
self.columns.push(name);
self.values.push(value);
self
}
pub fn on_conflict(mut self, conflict: OnConflict) -> Self {
self.on_conflict = Some(conflict);
self
}
pub fn returning(mut self, cols: impl IntoIterator<Item = ColumnName>) -> Self {
self.returning.extend(cols);
self
}
}
impl UpdateStmt {
pub fn new(table: TableName) -> Self {
Self {
table,
assignments: Vec::new(),
where_: None,
returning: Vec::new(),
}
}
pub fn set(mut self, column: ColumnName, value: Expr) -> Self {
self.assignments.push(UpdateAssignment::new(column, value));
self
}
pub fn where_(mut self, expr: Expr) -> Self {
self.where_ = Some(expr);
self
}
pub fn and_where(mut self, expr: Expr) -> Self {
self.where_ = Some(match self.where_ {
Some(existing) => existing.and(expr),
None => expr,
});
self
}
pub fn returning(mut self, cols: impl IntoIterator<Item = ColumnName>) -> Self {
self.returning.extend(cols);
self
}
}
impl DeleteStmt {
pub fn new(table: TableName) -> Self {
Self {
table,
where_: None,
returning: Vec::new(),
}
}
pub fn where_(mut self, expr: Expr) -> Self {
self.where_ = Some(expr);
self
}
pub fn and_where(mut self, expr: Expr) -> Self {
self.where_ = Some(match self.where_ {
Some(existing) => existing.and(expr),
None => expr,
});
self
}
pub fn returning(mut self, cols: impl IntoIterator<Item = ColumnName>) -> Self {
self.returning.extend(cols);
self
}
}
impl InsertSelectStmt {
pub fn new(table: TableName, unnest: Unnest) -> Self {
Self {
table,
columns: Vec::new(),
select_exprs: Vec::new(),
unnest,
on_conflict: None,
returning: Vec::new(),
}
}
pub fn column(mut self, name: ColumnName, expr: Expr) -> Self {
self.columns.push(name);
self.select_exprs.push(expr);
self
}
pub fn on_conflict(mut self, conflict: OnConflict) -> Self {
self.on_conflict = Some(conflict);
self
}
pub fn returning(mut self, cols: impl IntoIterator<Item = ColumnName>) -> Self {
self.returning.extend(cols);
self
}
}