1pub(crate) mod batch_update;
2pub(crate) mod changeset;
3pub(super) mod target;
4
5use private::AllowFilterForUpdate;
6
7use crate::QuerySource;
8use crate::backend::DieselReserveSpecialization;
9use crate::dsl::{Filter, IntoBoxed, IntoBoxedClone};
10use crate::expression::{
11 AppearsOnTable, Expression, MixedAggregates, SelectableExpression, ValidGrouping, is_aggregate,
12};
13use crate::query_builder::returning::{
14 NoReturningClause, ReturningClause, ReturningQuerySource, UpdateStmt,
15};
16use crate::query_builder::where_clause::*;
17use crate::query_builder::*;
18use crate::query_dsl::RunQueryDslSupport;
19use crate::query_dsl::methods::{BoxedCloneDsl, BoxedDsl, FilterDsl};
20use crate::query_source::Table;
21use crate::result::EmptyChangeset;
22use crate::result::Error::QueryBuilderError;
23
24pub(crate) use self::private::SetAutoTypeHelper;
25
26impl<T: QuerySource, U> UpdateStatement<T, U, SetNotCalled> {
27 pub(crate) fn new(target: UpdateTarget<T, U>) -> Self {
28 UpdateStatement {
29 from_clause: target.table.from_clause(),
30 where_clause: target.where_clause,
31 set_clause: SetClause::Immediate,
32 values: SetNotCalled,
33 returning: NoReturningClause,
34 }
35 }
36
37 pub fn set<V>(self, values: V) -> crate::dsl::Set<Self, V>
43 where
44 T: Table,
45 V: changeset::AsChangeset<Target = T>,
46 UpdateStatement<T, U, V::Changeset>: AsQuery,
47 {
48 UpdateStatement {
49 from_clause: self.from_clause,
50 where_clause: self.where_clause,
51 set_clause: <V as AsChangeset>::SET_CLAUSE,
52 values: values.as_changeset(),
53 returning: self.returning,
54 }
55 }
56}
57
58#[derive(#[automatically_derived]
impl<T: ::core::clone::Clone + QuerySource, U: ::core::clone::Clone,
V: ::core::clone::Clone, Ret: ::core::clone::Clone> ::core::clone::Clone
for UpdateStatement<T, U, V, Ret> where
T::FromClause: ::core::clone::Clone {
#[inline]
fn clone(&self) -> Self {
Self {
from_clause: ::core::clone::Clone::clone(&self.from_clause),
where_clause: ::core::clone::Clone::clone(&self.where_clause),
set_clause: ::core::clone::Clone::clone(&self.set_clause),
values: ::core::clone::Clone::clone(&self.values),
returning: ::core::clone::Clone::clone(&self.returning),
}
}
}Clone, #[automatically_derived]
impl<T: ::core::fmt::Debug + QuerySource, U: ::core::fmt::Debug,
V: ::core::fmt::Debug, Ret: ::core::fmt::Debug> ::core::fmt::Debug for
UpdateStatement<T, U, V, Ret> where T::FromClause: ::core::fmt::Debug {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"UpdateStatement", "from_clause", &self.from_clause,
"where_clause", &self.where_clause, "set_clause",
&self.set_clause, "values", &self.values, "returning",
&&self.returning)
}
}Debug)]
59#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
60pub struct UpdateStatement<T: QuerySource, U, V = SetNotCalled, Ret = NoReturningClause> {
66 from_clause: T::FromClause,
67 where_clause: U,
68 set_clause: SetClause,
69 values: V,
70 returning: Ret,
71}
72
73pub type BoxedUpdateStatement<'a, DB, T, V = SetNotCalled, Ret = NoReturningClause> =
75 UpdateStatement<T, BoxedWhereClause<'a, DB>, V, Ret>;
76
77pub type BoxedCloneUpdateStatement<'a, DB, T, V = SetNotCalled, Ret = NoReturningClause> =
79 UpdateStatement<T, BoxedCloneWhereClause<'a, DB>, V, Ret>;
80
81impl<T: QuerySource, U, V, Ret> UpdateStatement<T, U, V, Ret> {
82 pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
110 where
111 Self: FilterDsl<Predicate>,
112 {
113 FilterDsl::filter(self, predicate)
114 }
115
116 pub fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
159 where
160 DB: Backend,
161 Self: BoxedDsl<'a, DB>,
162 {
163 BoxedDsl::internal_into_boxed(self)
164 }
165
166 pub fn into_boxed_clone<'a, DB>(self) -> IntoBoxedClone<'a, Self, DB>
210 where
211 DB: Backend,
212 Self: BoxedCloneDsl<'a, DB>,
213 {
214 BoxedCloneDsl::internal_into_boxed_clone(self)
215 }
216}
217
218impl<T, U, V, Ret, Predicate> FilterDsl<Predicate> for UpdateStatement<T, U, V, Ret>
219where
220 T: QuerySource,
221 U: WhereAnd<Predicate>,
222 Predicate: AppearsOnTable<T>,
223{
224 type Output = UpdateStatement<T, U::Output, V, Ret>;
225
226 fn filter(self, predicate: Predicate) -> Self::Output {
227 UpdateStatement {
228 from_clause: self.from_clause,
229 where_clause: self.where_clause.and(predicate),
230 set_clause: self.set_clause,
231 values: self.values,
232 returning: self.returning,
233 }
234 }
235}
236
237impl<'a, T, U, V, Ret, DB> BoxedDsl<'a, DB> for UpdateStatement<T, U, V, Ret>
238where
239 T: QuerySource,
240 U: Into<BoxedWhereClause<'a, DB>>,
241{
242 type Output = BoxedUpdateStatement<'a, DB, T, V, Ret>;
243
244 fn internal_into_boxed(self) -> Self::Output {
245 UpdateStatement {
246 from_clause: self.from_clause,
247 where_clause: self.where_clause.into(),
248 set_clause: self.set_clause,
249 values: self.values,
250 returning: self.returning,
251 }
252 }
253}
254
255impl<'a, T, U, V, Ret, DB> BoxedCloneDsl<'a, DB> for UpdateStatement<T, U, V, Ret>
256where
257 T: QuerySource,
258 U: Into<BoxedCloneWhereClause<'a, DB>>,
259{
260 type Output = BoxedCloneUpdateStatement<'a, DB, T, V, Ret>;
261
262 fn internal_into_boxed_clone(self) -> Self::Output {
263 UpdateStatement {
264 from_clause: self.from_clause,
265 where_clause: self.where_clause.into(),
266 set_clause: self.set_clause,
267 values: self.values,
268 returning: self.returning,
269 }
270 }
271}
272
273impl<T, U, V, Ret, DB> QueryFragment<DB> for UpdateStatement<T, U, V, Ret>
274where
275 DB: Backend + DieselReserveSpecialization,
276 T: Table,
277 T::FromClause: QueryFragment<DB>,
278 U: QueryFragment<DB>,
279 V: QueryFragment<DB> + AllowFilterForUpdate<U>,
280 Ret: QueryFragment<DB>,
281{
282 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
283 if self.values.is_noop(out.backend())? {
284 return Err(QueryBuilderError(Box::new(EmptyChangeset)));
285 }
286
287 out.unsafe_to_cache_prepared();
288 out.push_sql("UPDATE ");
289 self.from_clause.walk_ast(out.reborrow())?;
290 self.set_clause.walk_ast(out.reborrow())?;
291 self.values.walk_ast(out.reborrow())?;
292 self.where_clause.walk_ast(out.reborrow())?;
293 self.returning.walk_ast(out.reborrow())?;
294 Ok(())
295 }
296}
297
298impl<T, U, V, Ret> QueryId for UpdateStatement<T, U, V, Ret>
299where
300 T: QuerySource,
301{
302 type QueryId = ();
303
304 const HAS_STATIC_QUERY_ID: bool = false;
305}
306
307impl<T, U, V> AsQuery for UpdateStatement<T, U, V, NoReturningClause>
308where
309 T: Table,
310 UpdateStatement<T, U, V, ReturningClause<T::AllColumns>>: Query,
311 T::AllColumns: SelectableExpression<ReturningQuerySource<UpdateStmt, T>> + ValidGrouping<()>,
312 <T::AllColumns as ValidGrouping<()>>::IsAggregate:
313 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
314{
315 type SqlType = <Self::Query as Query>::SqlType;
316 type Query = UpdateStatement<T, U, V, ReturningClause<T::AllColumns>>;
317
318 fn as_query(self) -> Self::Query {
319 self.returning(T::all_columns())
320 }
321}
322
323impl<T, U, V, Ret> Query for UpdateStatement<T, U, V, ReturningClause<Ret>>
324where
325 T: Table,
326 Ret: SelectableExpression<ReturningQuerySource<UpdateStmt, T>> + ValidGrouping<()>,
327 Ret::IsAggregate: MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
328{
329 type SqlType = <Ret as Expression>::SqlType;
330}
331
332impl<T: QuerySource, U, V, Ret> RunQueryDslSupport for UpdateStatement<T, U, V, Ret> {}
333
334impl<T: QuerySource, U, V> UpdateStatement<T, U, V, NoReturningClause> {
335 pub fn returning<E>(self, returns: E) -> UpdateStatement<T, U, V, ReturningClause<E>>
392 where
393 T: Table,
394 UpdateStatement<T, U, V, ReturningClause<E>>: Query,
395 {
396 UpdateStatement {
397 from_clause: self.from_clause,
398 where_clause: self.where_clause,
399 set_clause: self.set_clause,
400 values: self.values,
401 returning: ReturningClause(returns),
402 }
403 }
404}
405
406#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SetNotCalled {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "SetNotCalled")
}
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SetNotCalled { }
#[automatically_derived]
impl ::core::clone::Clone for SetNotCalled {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SetNotCalled { }Copy)]
408pub struct SetNotCalled;
409
410pub(crate) mod private {
411 use crate::backend::Backend;
412 use crate::query_builder::where_clause::{
413 BoxedCloneWhereClause, BoxedWhereClause, NoWhereClause, WhereClause,
414 };
415
416 use super::changeset::Assign;
417
418 #[allow(unreachable_pub)]
424 pub trait SetAutoTypeHelper<Changes> {
425 type Out;
426 }
427
428 impl<T, W, Changes> SetAutoTypeHelper<Changes> for crate::query_builder::UpdateStatement<T, W>
429 where
430 T: crate::QuerySource,
431 Changes: crate::AsChangeset,
432 {
433 type Out = crate::query_builder::UpdateStatement<T, W, Changes::Changeset>;
434 }
435
436 #[diagnostic::on_unimplemented(
438 message = "cannot apply a `WHERE` clause to batch updates",
439 note = "the information about which rows to update are provided as part of the values"
440 )]
441 pub trait AllowFilterForUpdate<P> {}
442
443 impl<U> AllowFilterForUpdate<NoWhereClause> for U {}
444
445 impl<W, C, B> AllowFilterForUpdate<WhereClause<W>> for Assign<C, B> {}
446 impl<W, T> AllowFilterForUpdate<WhereClause<W>> for Option<T> where
447 T: AllowFilterForUpdate<WhereClause<W>>
448 {
449 }
450
451 impl<'a, DB, C, B> AllowFilterForUpdate<BoxedWhereClause<'a, DB>> for Assign<C, B> where DB: Backend {}
452 impl<'a, DB, T> AllowFilterForUpdate<BoxedWhereClause<'a, DB>> for Option<T>
453 where
454 DB: Backend,
455 T: AllowFilterForUpdate<BoxedWhereClause<'a, DB>>,
456 {
457 }
458
459 impl<'a, DB, C, B> AllowFilterForUpdate<BoxedCloneWhereClause<'a, DB>> for Assign<C, B> where
460 DB: Backend
461 {
462 }
463 impl<'a, DB, T> AllowFilterForUpdate<BoxedCloneWhereClause<'a, DB>> for Option<T>
464 where
465 DB: Backend,
466 T: AllowFilterForUpdate<BoxedCloneWhereClause<'a, DB>>,
467 {
468 }
469}
470
471#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SetClause { }
#[automatically_derived]
impl ::core::clone::Clone for SetClause {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SetClause { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for SetClause {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
SetClause::Immediate => "Immediate",
SetClause::Delegated => "Delegated",
})
}
}Debug)]
484pub enum SetClause {
485 Immediate,
486 Delegated,
487}
488
489impl<DB> QueryFragment<DB> for SetClause
490where
491 DB: Backend,
492{
493 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
494 if let SetClause::Immediate = self {
495 out.push_sql(" SET ");
496 }
497 Ok(())
498 }
499}