use super::Query;
use crate::{
Executor, Result,
schema::{Load, Model},
};
use std::{fmt, marker::PhantomData};
use toasty_core::stmt;
pub struct Update<T> {
pub(crate) untyped: stmt::Update,
_p: PhantomData<T>,
}
impl<T> Update<T> {
pub fn new(selection: Query<T>) -> Self {
let mut stmt = selection.untyped.update();
stmt.returning = Some(stmt::Returning::Changed);
Self {
untyped: stmt,
_p: PhantomData,
}
}
pub const fn from_untyped(untyped: stmt::Update) -> Self {
Self {
untyped,
_p: PhantomData,
}
}
pub fn as_untyped_mut(&mut self) -> &mut stmt::Update {
&mut self.untyped
}
pub fn set_assignments(&mut self, assignments: stmt::Assignments) {
self.untyped.assignments = assignments;
}
pub fn set(&mut self, field: impl Into<stmt::Projection>, expr: impl Into<stmt::Expr>) {
self.untyped.assignments.set(field, expr);
}
pub fn insert(&mut self, field: impl Into<stmt::Projection>, expr: impl Into<stmt::Expr>) {
self.untyped.assignments.insert(field, expr);
}
pub fn remove(&mut self, field: impl Into<stmt::Projection>, expr: impl Into<stmt::Expr>) {
self.untyped.assignments.remove(field, expr);
}
pub fn set_returning_none(&mut self) {
self.untyped.returning = None;
}
pub fn into_untyped(self) -> stmt::Statement {
self.untyped.into()
}
}
impl<T: Load> Update<T> {
pub async fn exec(self, executor: &mut dyn Executor) -> Result<T::Output> {
executor.exec(self.into()).await
}
}
impl<M> Clone for Update<M> {
fn clone(&self) -> Self {
Self {
untyped: self.untyped.clone(),
_p: PhantomData,
}
}
}
impl<M: Model> Default for Update<M> {
fn default() -> Self {
Self {
untyped: stmt::Update {
target: stmt::UpdateTarget::Model(M::id()),
assignments: stmt::Assignments::default(),
filter: stmt::Filter::new(stmt::Expr::from(false)),
condition: stmt::Condition::default(),
returning: Some(stmt::Returning::Changed),
},
_p: PhantomData,
}
}
}
impl<M> AsRef<stmt::Update> for Update<M> {
fn as_ref(&self) -> &stmt::Update {
&self.untyped
}
}
impl<M> AsMut<stmt::Update> for Update<M> {
fn as_mut(&mut self) -> &mut stmt::Update {
&mut self.untyped
}
}
impl<M> fmt::Debug for Update<M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.untyped.fmt(f)
}
}