use crate::expr::{Condition, Expr, IntoCondition, Order};
use crate::iden::{ColumnRef, Ident, IntoIden, TableRef};
use crate::value::Value;
#[derive(Debug)]
pub struct Query;
impl Query {
pub fn select() -> Select {
Select::default()
}
pub fn insert() -> Insert {
Insert::default()
}
pub fn update() -> Update {
Update::default()
}
pub fn delete() -> Delete {
Delete::default()
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum SelectItem {
Expr(Expr),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum JoinType {
Inner,
Left,
Cross,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Join {
pub kind: JoinType,
pub table: TableRef,
pub on: Option<Expr>,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub enum Returning {
#[default]
None,
All,
Columns(Vec<ColumnRef>),
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Select {
pub(crate) distinct: bool,
pub(crate) items: Vec<SelectItem>,
pub(crate) from: Vec<TableRef>,
pub(crate) from_subquery: Option<(Box<Select>, Ident)>,
pub(crate) joins: Vec<Join>,
pub(crate) r#where: Condition,
pub(crate) group_by: Vec<Expr>,
pub(crate) having: Condition,
pub(crate) order_by: Vec<(Expr, Order)>,
pub(crate) limit: Option<u64>,
pub(crate) offset: Option<u64>,
}
impl Select {
pub fn new() -> Self {
Self {
r#where: Condition::all(),
having: Condition::all(),
..Default::default()
}
}
#[must_use]
pub fn distinct(mut self) -> Self {
self.distinct = true;
self
}
#[must_use]
pub fn column(mut self, column: impl Into<ColumnRef>) -> Self {
self.items
.push(SelectItem::Expr(Expr::Column(column.into())));
self
}
#[must_use]
pub fn columns<C: Into<ColumnRef>>(mut self, columns: impl IntoIterator<Item = C>) -> Self {
for c in columns {
self = self.column(c);
}
self
}
#[must_use]
pub fn expr(mut self, expr: Expr) -> Self {
self.items.push(SelectItem::Expr(expr));
self
}
#[must_use]
pub fn expr_as(self, expr: Expr, alias: impl IntoIden) -> Self {
self.expr(expr.alias(alias))
}
pub fn has_items(&self) -> bool {
!self.items.is_empty()
}
#[must_use]
pub fn clear_items(mut self) -> Self {
self.items.clear();
self
}
#[must_use]
pub fn from(mut self, table: impl Into<TableRef>) -> Self {
self.from.push(table.into());
self
}
#[must_use]
pub fn from_subquery(mut self, subquery: Select, alias: impl IntoIden) -> Self {
self.from_subquery = Some((Box::new(subquery), alias.into_iden()));
self
}
#[must_use]
pub fn join(
mut self,
kind: JoinType,
table: impl Into<TableRef>,
on: impl IntoCondition,
) -> Self {
self.joins.push(Join {
kind,
table: table.into(),
on: on.into_condition().into_expr(),
});
self
}
#[must_use]
pub fn inner_join(self, table: impl Into<TableRef>, on: impl IntoCondition) -> Self {
self.join(JoinType::Inner, table, on)
}
#[must_use]
pub fn left_join(self, table: impl Into<TableRef>, on: impl IntoCondition) -> Self {
self.join(JoinType::Left, table, on)
}
#[must_use]
pub fn and_where(mut self, cond: impl IntoCondition) -> Self {
self.r#where = std::mem::take(&mut self.r#where).add(cond);
self
}
#[must_use]
pub fn cond_where(mut self, cond: impl IntoCondition) -> Self {
self.r#where = cond.into_condition();
self
}
#[must_use]
pub fn group_by(mut self, expr: Expr) -> Self {
self.group_by.push(expr);
self
}
#[must_use]
pub fn and_having(mut self, cond: impl IntoCondition) -> Self {
self.having = std::mem::take(&mut self.having).add(cond);
self
}
#[must_use]
pub fn order_by(mut self, column: impl Into<ColumnRef>, order: Order) -> Self {
self.order_by.push((Expr::Column(column.into()), order));
self
}
#[must_use]
pub fn order_by_expr(mut self, expr: Expr, order: Order) -> Self {
self.order_by.push((expr, order));
self
}
#[must_use]
pub fn clear_order_by(mut self) -> Self {
self.order_by.clear();
self
}
#[must_use]
pub fn limit(mut self, limit: u64) -> Self {
self.limit = Some(limit);
self
}
#[must_use]
pub fn reset_limit(mut self) -> Self {
self.limit = None;
self
}
#[must_use]
pub fn offset(mut self, offset: u64) -> Self {
self.offset = Some(offset);
self
}
#[must_use]
pub fn reset_offset(mut self) -> Self {
self.offset = None;
self
}
pub fn from_tables(&self) -> &[TableRef] {
&self.from
}
pub fn joins(&self) -> &[Join] {
&self.joins
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct OnConflict {
pub(crate) target: Vec<Ident>,
pub(crate) action: ConflictAction,
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum ConflictAction {
Nothing,
Update(Vec<(Ident, Expr)>),
}
impl OnConflict {
pub fn do_nothing<C: IntoIden>(columns: impl IntoIterator<Item = C>) -> Self {
Self {
target: columns.into_iter().map(IntoIden::into_iden).collect(),
action: ConflictAction::Nothing,
}
}
pub fn update_columns<C: IntoIden, U: IntoIden>(
columns: impl IntoIterator<Item = C>,
update: impl IntoIterator<Item = U>,
) -> Self {
let sets = update
.into_iter()
.map(|c| {
let c = c.into_iden();
let excluded =
Expr::Column(ColumnRef::TableColumn("excluded".into_iden(), c.clone()));
(c, excluded)
})
.collect();
Self {
target: columns.into_iter().map(IntoIden::into_iden).collect(),
action: ConflictAction::Update(sets),
}
}
pub fn update_exprs<C: IntoIden, U: IntoIden>(
columns: impl IntoIterator<Item = C>,
sets: impl IntoIterator<Item = (U, Expr)>,
) -> Self {
Self {
target: columns.into_iter().map(IntoIden::into_iden).collect(),
action: ConflictAction::Update(
sets.into_iter().map(|(c, e)| (c.into_iden(), e)).collect(),
),
}
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Insert {
pub(crate) table: Option<TableRef>,
pub(crate) columns: Vec<Ident>,
pub(crate) rows: Vec<Vec<Expr>>,
pub(crate) default_values: bool,
pub(crate) on_conflict: Option<OnConflict>,
pub(crate) returning: Returning,
pub(crate) select: Option<Box<Select>>,
}
impl Insert {
#[must_use]
pub fn into_table(mut self, table: impl Into<TableRef>) -> Self {
self.table = Some(table.into());
self
}
#[must_use]
pub fn columns<C: IntoIden>(mut self, columns: impl IntoIterator<Item = C>) -> Self {
self.columns = columns.into_iter().map(IntoIden::into_iden).collect();
self
}
#[must_use]
pub fn values<V: Into<Expr>>(mut self, row: impl IntoIterator<Item = V>) -> Self {
self.rows.push(row.into_iter().map(Into::into).collect());
self
}
#[must_use]
pub fn default_values(mut self) -> Self {
self.default_values = true;
self
}
#[must_use]
pub fn select_from(mut self, select: Select) -> Self {
self.select = Some(Box::new(select));
self
}
#[must_use]
pub fn on_conflict(mut self, on_conflict: OnConflict) -> Self {
self.on_conflict = Some(on_conflict);
self
}
#[must_use]
pub fn returning(mut self, returning: Returning) -> Self {
self.returning = returning;
self
}
#[must_use]
pub fn returning_all(self) -> Self {
self.returning(Returning::All)
}
pub fn row_count(&self) -> usize {
self.rows.len()
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Update {
pub(crate) table: Option<TableRef>,
pub(crate) sets: Vec<(Ident, Expr)>,
pub(crate) r#where: Option<Condition>,
pub(crate) returning: Returning,
pub(crate) limit: Option<u64>,
}
impl Update {
#[must_use]
pub fn table(mut self, table: impl Into<TableRef>) -> Self {
self.table = Some(table.into());
self
}
#[must_use]
pub fn value(mut self, column: impl IntoIden, value: impl Into<Expr>) -> Self {
self.sets.push((column.into_iden(), value.into()));
self
}
#[must_use]
pub fn values<C: IntoIden, V: Into<Expr>>(
mut self,
sets: impl IntoIterator<Item = (C, V)>,
) -> Self {
for (c, v) in sets {
self = self.value(c, v);
}
self
}
#[must_use]
pub fn and_where(mut self, cond: impl IntoCondition) -> Self {
let current = self.r#where.take().unwrap_or_else(Condition::all);
self.r#where = Some(current.add(cond));
self
}
#[must_use]
pub fn returning(mut self, returning: Returning) -> Self {
self.returning = returning;
self
}
#[must_use]
pub fn returning_all(self) -> Self {
self.returning(Returning::All)
}
pub fn has_sets(&self) -> bool {
!self.sets.is_empty()
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Delete {
pub(crate) table: Option<TableRef>,
pub(crate) r#where: Option<Condition>,
pub(crate) returning: Returning,
}
impl Delete {
#[must_use]
pub fn from_table(mut self, table: impl Into<TableRef>) -> Self {
self.table = Some(table.into());
self
}
#[must_use]
pub fn and_where(mut self, cond: impl IntoCondition) -> Self {
let current = self.r#where.take().unwrap_or_else(Condition::all);
self.r#where = Some(current.add(cond));
self
}
#[must_use]
pub fn returning(mut self, returning: Returning) -> Self {
self.returning = returning;
self
}
}
impl From<Value> for SelectItem {
fn from(v: Value) -> Self {
SelectItem::Expr(Expr::Value(v))
}
}