1use core::marker::PhantomData;
2
3use crate::backend::{DieselReserveSpecialization, sql_dialect};
4use crate::dsl::AsExprOf;
5use crate::expression::subselect::{ValidSubselect, ValidSubselectGrouping};
6use crate::expression::*;
7use crate::insertable::Insertable;
8use crate::query_builder::combination_clause::*;
9use crate::query_builder::distinct_clause::DistinctClause;
10use crate::query_builder::group_by_clause::ValidGroupByClause;
11use crate::query_builder::having_clause::HavingClause;
12use crate::query_builder::insert_statement::InsertFromSelect;
13use crate::query_builder::limit_clause::LimitClause;
14use crate::query_builder::limit_offset_clause::BoxedCloneLimitOffsetClause;
15use crate::query_builder::offset_clause::OffsetClause;
16use crate::query_builder::order_clause::OrderClause;
17use crate::query_builder::where_clause::{BoxedCloneWhereClause, WhereAnd, WhereOr};
18use crate::query_builder::*;
19use crate::query_dsl::methods::*;
20use crate::query_dsl::*;
21use crate::query_source::joins::*;
22use crate::query_source::{QuerySource, Table};
23use crate::sql_types::{BigInt, BoolOrNullableBool, IntoNullable};
24use alloc::sync::Arc;
25
26#[allow(missing_debug_implementations)]
32#[doc = " This type represents a boxed select query"]
#[doc = ""]
#[doc = " Using this type directly is only meaningful for custom backends"]
#[doc = " that need to provide a custom [`QueryFragment`] implementation"]
#[allow(missing_debug_implementations)]
#[non_exhaustive]
pub struct BoxedCloneSelectStatement<'a, ST, QS, DB, GB = ()> {
#[doc = " The select clause of the query"]
pub select: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
#[doc = " The from clause of the query"]
pub from: QS,
#[doc = " The distinct clause of the query"]
pub distinct: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
#[doc = " The where clause of the query"]
pub where_clause: BoxedCloneWhereClause<'a, DB>,
#[doc = " The order clause of the query"]
pub order: Option<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>>,
#[doc = " The combined limit/offset clause of the query"]
pub limit_offset: BoxedCloneLimitOffsetClause<'a, DB>,
#[doc = " The group by clause of the query"]
pub group_by: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
#[doc = " The having clause of the query"]
pub having: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
_marker: PhantomData<(ST, GB)>,
}#[diesel_derives::__diesel_public_if(
33 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
34 public_fields(
35 select,
36 from,
37 distinct,
38 where_clause,
39 order,
40 limit_offset,
41 group_by,
42 having
43 )
44)]
45pub struct BoxedCloneSelectStatement<'a, ST, QS, DB, GB = ()> {
46 select: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
48 from: QS,
50 distinct: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
52 where_clause: BoxedCloneWhereClause<'a, DB>,
54 order: Option<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>>,
56 limit_offset: BoxedCloneLimitOffsetClause<'a, DB>,
58 group_by: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
60 having: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
62 _marker: PhantomData<(ST, GB)>,
63}
64
65impl<ST, QS: Clone, DB, GB> Clone for BoxedCloneSelectStatement<'_, ST, QS, DB, GB> {
66 fn clone(&self) -> Self {
67 Self {
68 select: Arc::clone(&self.select),
69 from: self.from.clone(),
70 distinct: Arc::clone(&self.distinct),
71 where_clause: self.where_clause.clone(),
72 order: self.order.as_ref().map(Arc::clone),
73 limit_offset: self.limit_offset.clone(),
74 group_by: Arc::clone(&self.group_by),
75 having: Arc::clone(&self.having),
76 _marker: PhantomData,
77 }
78 }
79}
80
81impl<'a, ST, QS: QuerySource, DB, GB> BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB> {
82 #[allow(clippy::too_many_arguments)]
83 pub(crate) fn new<S, G>(
84 select: S,
85 from: FromClause<QS>,
86 distinct: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
87 where_clause: BoxedCloneWhereClause<'a, DB>,
88 order: Option<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>>,
89 limit_offset: BoxedCloneLimitOffsetClause<'a, DB>,
90 group_by: G,
91 having: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
92 ) -> Self
93 where
94 DB: Backend,
95 G: ValidGroupByClause<Expressions = GB> + QueryFragment<DB> + Send + Sync + 'a,
96 S: SelectClauseExpression<FromClause<QS>, SelectClauseSqlType = ST>
97 + QueryFragment<DB>
98 + Send
99 + Sync
100 + 'a,
101 S::Selection: ValidGrouping<GB>,
102 {
103 BoxedCloneSelectStatement {
104 select: Arc::new(select),
105 from,
106 distinct,
107 where_clause,
108 order,
109 limit_offset,
110 group_by: Arc::new(group_by),
111 having,
112 _marker: PhantomData,
113 }
114 }
115}
116
117impl<'a, ST, DB, GB> BoxedCloneSelectStatement<'a, ST, NoFromClause, DB, GB> {
118 #[allow(clippy::too_many_arguments)]
119 pub(crate) fn new_no_from_clause<S, G>(
120 select: S,
121 from: NoFromClause,
122 distinct: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
123 where_clause: BoxedCloneWhereClause<'a, DB>,
124 order: Option<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>>,
125 limit_offset: BoxedCloneLimitOffsetClause<'a, DB>,
126 group_by: G,
127 having: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
128 ) -> Self
129 where
130 DB: Backend,
131 G: ValidGroupByClause<Expressions = GB> + QueryFragment<DB> + Send + Sync + 'a,
132 S: SelectClauseExpression<NoFromClause, SelectClauseSqlType = ST>
133 + QueryFragment<DB>
134 + Send
135 + Sync
136 + 'a,
137 S::Selection: ValidGrouping<GB>,
138 {
139 BoxedCloneSelectStatement {
140 select: Arc::new(select),
141 from,
142 distinct,
143 where_clause,
144 order,
145 limit_offset,
146 group_by: Arc::new(group_by),
147 having,
148 _marker: PhantomData,
149 }
150 }
151}
152
153#[doc(hidden)] pub trait BoxedCloneQueryHelper<'a, QS, DB> {
156 fn build_query<'b, 'c>(
157 &'b self,
158 out: AstPass<'_, 'c, DB>,
159 where_clause_handler: impl Fn(
160 &'b BoxedCloneWhereClause<'a, DB>,
161 AstPass<'_, 'c, DB>,
162 ) -> QueryResult<()>,
163 ) -> QueryResult<()>
164 where
165 DB: Backend + 'b,
166 QS: QueryFragment<DB>,
167 BoxedCloneLimitOffsetClause<'a, DB>: QueryFragment<DB>,
168 'a: 'b,
169 'b: 'c;
170}
171
172impl<'a, ST, QS, DB, GB> BoxedCloneQueryHelper<'a, QS, DB>
173 for BoxedCloneSelectStatement<'a, ST, QS, DB, GB>
174{
175 fn build_query<'b, 'c>(
176 &'b self,
177 mut out: AstPass<'_, 'c, DB>,
178 where_clause_handler: impl Fn(
179 &'b BoxedCloneWhereClause<'a, DB>,
180 AstPass<'_, 'c, DB>,
181 ) -> QueryResult<()>,
182 ) -> QueryResult<()>
183 where
184 DB: Backend,
185 QS: QueryFragment<DB>,
186 BoxedCloneLimitOffsetClause<'a, DB>: QueryFragment<DB>,
187 'b: 'c,
188 {
189 out.push_sql("SELECT ");
190 self.distinct.walk_ast(out.reborrow())?;
191 self.select.walk_ast(out.reborrow())?;
192 self.from.walk_ast(out.reborrow())?;
193 where_clause_handler(&self.where_clause, out.reborrow())?;
194 self.group_by.walk_ast(out.reborrow())?;
195 self.having.walk_ast(out.reborrow())?;
196
197 if let Some(ref order) = self.order {
198 out.push_sql(" ORDER BY ");
199 order.walk_ast(out.reborrow())?;
200 }
201 self.limit_offset.walk_ast(out.reborrow())?;
202 Ok(())
203 }
204}
205
206impl<ST, QS, DB, GB> Query for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
207where
208 DB: Backend,
209{
210 type SqlType = ST;
211}
212
213impl<ST, QS, DB, GB> SelectQuery for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
214where
215 DB: Backend,
216{
217 type SqlType = ST;
218}
219
220impl<ST, QS, QS2, DB, GB> ValidSubselect<QS2> for BoxedCloneSelectStatement<'_, ST, QS, DB, GB> where
221 Self: Query<SqlType = ST>
222{
223}
224
225impl<ST, QS, DB, GB, OuterGB> ValidSubselectGrouping<OuterGB>
228 for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
229{
230 type IsAggregate = is_aggregate::Never;
231}
232
233impl<ST, QS, DB, GB> QueryFragment<DB> for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
234where
235 DB: Backend,
236 Self: QueryFragment<DB, DB::SelectStatementSyntax>,
237{
238 fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
239 <Self as QueryFragment<DB, DB::SelectStatementSyntax>>::walk_ast(self, pass)
240 }
241}
242
243impl<'a, ST, QS, DB, GB>
244 QueryFragment<DB, sql_dialect::select_statement_syntax::AnsiSqlSelectStatement>
245 for BoxedCloneSelectStatement<'a, ST, QS, DB, GB>
246where
247 DB: Backend<
248 SelectStatementSyntax = sql_dialect::select_statement_syntax::AnsiSqlSelectStatement,
249 > + DieselReserveSpecialization,
250 QS: QueryFragment<DB>,
251 BoxedCloneLimitOffsetClause<'a, DB>: QueryFragment<DB>,
252{
253 fn walk_ast<'b>(&'b self, out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
254 self.build_query(out, |where_clause, out| where_clause.walk_ast(out))
255 }
256}
257
258impl<ST, QS, DB, GB> QueryId for BoxedCloneSelectStatement<'_, ST, QS, DB, GB> {
259 type QueryId = ();
260
261 const HAS_STATIC_QUERY_ID: bool = false;
262}
263
264impl<'a, ST, QS, DB, Rhs, Kind, On, GB> InternalJoinDsl<Rhs, Kind, On>
265 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
266where
267 QS: QuerySource,
268 Rhs: QuerySource,
269 JoinOn<Join<QS, Rhs, Kind>, On>: QuerySource,
270 BoxedCloneSelectStatement<'a, ST, FromClause<JoinOn<Join<QS, Rhs, Kind>, On>>, DB, GB>: AsQuery,
271{
272 type Output =
273 BoxedCloneSelectStatement<'a, ST, FromClause<JoinOn<Join<QS, Rhs, Kind>, On>>, DB, GB>;
274
275 fn join(self, rhs: Rhs, kind: Kind, on: On) -> Self::Output {
276 BoxedCloneSelectStatement {
277 select: self.select,
278 from: FromClause::new(Join::new(self.from.source, rhs, kind).on(on)),
279 distinct: self.distinct,
280 where_clause: self.where_clause,
281 order: self.order,
282 limit_offset: self.limit_offset,
283 group_by: self.group_by,
284 having: self.having,
285 _marker: PhantomData,
286 }
287 }
288}
289
290impl<ST, QS, DB, GB> DistinctDsl for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
291where
292 DB: Backend,
293 DistinctClause: QueryFragment<DB>,
294{
295 type Output = Self;
296
297 fn distinct(mut self) -> Self::Output {
298 self.distinct = Arc::new(DistinctClause);
299 self
300 }
301}
302
303impl<'a, ST, QS, DB, GB> BoxedCloneSelectStatement<'a, ST, QS, DB, GB> {
304 fn with_select<NewST>(
306 self,
307 select: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
308 ) -> BoxedCloneSelectStatement<'a, NewST, QS, DB, GB> {
309 BoxedCloneSelectStatement {
310 select,
311 from: self.from,
312 distinct: self.distinct,
313 where_clause: self.where_clause,
314 order: self.order,
315 limit_offset: self.limit_offset,
316 group_by: self.group_by,
317 having: self.having,
318 _marker: PhantomData,
319 }
320 }
321}
322
323impl<'a, ST, QS, DB, Selection, GB> SelectDsl<Selection>
324 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
325where
326 DB: Backend,
327 QS: QuerySource,
328 Selection: SelectableExpression<QS> + QueryFragment<DB> + ValidGrouping<GB> + Send + Sync + 'a,
329{
330 type Output = BoxedCloneSelectStatement<'a, Selection::SqlType, FromClause<QS>, DB, GB>;
331
332 fn select(self, selection: Selection) -> Self::Output {
333 self.with_select(Arc::new(selection))
334 }
335}
336
337impl<'a, ST, DB, Selection, GB> SelectDsl<Selection>
338 for BoxedCloneSelectStatement<'a, ST, NoFromClause, DB, GB>
339where
340 DB: Backend,
341 Selection: SelectableExpression<NoFromClause>
342 + QueryFragment<DB>
343 + ValidGrouping<GB>
344 + Send
345 + Sync
346 + 'a,
347{
348 type Output = BoxedCloneSelectStatement<'a, Selection::SqlType, NoFromClause, DB, GB>;
349
350 fn select(self, selection: Selection) -> Self::Output {
351 self.with_select(Arc::new(selection))
352 }
353}
354
355impl<'a, ST, QS, DB, Predicate, GB> FilterDsl<Predicate>
356 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
357where
358 QS: QuerySource,
359 BoxedCloneWhereClause<'a, DB>: WhereAnd<Predicate, Output = BoxedCloneWhereClause<'a, DB>>,
360 Predicate: AppearsOnTable<QS> + NonAggregate,
361 Predicate::SqlType: BoolOrNullableBool,
362{
363 type Output = Self;
364
365 fn filter(mut self, predicate: Predicate) -> Self::Output {
366 self.where_clause = self.where_clause.and(predicate);
367 self
368 }
369}
370
371impl<'a, ST, DB, Predicate, GB> FilterDsl<Predicate>
372 for BoxedCloneSelectStatement<'a, ST, NoFromClause, DB, GB>
373where
374 BoxedCloneWhereClause<'a, DB>: WhereAnd<Predicate, Output = BoxedCloneWhereClause<'a, DB>>,
375 Predicate: AppearsOnTable<NoFromClause> + NonAggregate,
376 Predicate::SqlType: BoolOrNullableBool,
377{
378 type Output = Self;
379
380 fn filter(mut self, predicate: Predicate) -> Self::Output {
381 self.where_clause = self.where_clause.and(predicate);
382 self
383 }
384}
385
386impl<'a, ST, QS, DB, Predicate, GB> OrFilterDsl<Predicate>
387 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
388where
389 QS: QuerySource,
390 BoxedCloneWhereClause<'a, DB>: WhereOr<Predicate, Output = BoxedCloneWhereClause<'a, DB>>,
391 Predicate: AppearsOnTable<QS> + NonAggregate,
392 Predicate::SqlType: BoolOrNullableBool,
393{
394 type Output = Self;
395
396 fn or_filter(mut self, predicate: Predicate) -> Self::Output {
397 self.where_clause = self.where_clause.or(predicate);
398 self
399 }
400}
401
402impl<'a, ST, DB, Predicate, GB> OrFilterDsl<Predicate>
403 for BoxedCloneSelectStatement<'a, ST, NoFromClause, DB, GB>
404where
405 BoxedCloneWhereClause<'a, DB>: WhereOr<Predicate, Output = BoxedCloneWhereClause<'a, DB>>,
406 Predicate: AppearsOnTable<NoFromClause> + NonAggregate,
407 Predicate::SqlType: BoolOrNullableBool,
408{
409 type Output = Self;
410
411 fn or_filter(mut self, predicate: Predicate) -> Self::Output {
412 self.where_clause = self.where_clause.or(predicate);
413 self
414 }
415}
416
417impl<ST, QS, DB, GB> LimitDsl for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
418where
419 DB: Backend,
420 LimitClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
421{
422 type Output = Self;
423
424 fn limit(mut self, limit: i64) -> Self::Output {
425 self.limit_offset.limit = Some(Arc::new(LimitClause(limit.into_sql::<BigInt>())));
426 self
427 }
428}
429
430impl<ST, QS, DB, GB> OffsetDsl for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
431where
432 DB: Backend,
433 OffsetClause<AsExprOf<i64, BigInt>>: QueryFragment<DB>,
434{
435 type Output = Self;
436
437 fn offset(mut self, offset: i64) -> Self::Output {
438 self.limit_offset.offset = Some(Arc::new(OffsetClause(offset.into_sql::<BigInt>())));
439 self
440 }
441}
442
443impl<'a, ST, QS, DB, Order, GB> OrderDsl<Order>
445 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
446where
447 DB: Backend,
448 QS: QuerySource,
449 Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + Sync + 'a,
450{
451 type Output = Self;
452
453 fn order(mut self, order: Order) -> Self::Output {
454 self.order = OrderClause(order).into();
455 self
456 }
457}
458
459impl<'a, ST, QS, DB, Order, GB> ThenOrderDsl<Order>
460 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
461where
462 DB: Backend + 'a,
463 QS: QuerySource,
464 Order: QueryFragment<DB> + AppearsOnTable<QS> + Send + Sync + 'a,
465{
466 type Output = Self;
467
468 fn then_order_by(mut self, order: Order) -> Self::Output {
469 self.order = match self.order {
470 Some(old) => Some(Arc::new((old, order))),
471 None => Some(Arc::new(order)),
472 };
473 self
474 }
475}
476
477impl<ST, QS, DB, Rhs> JoinTo<Rhs> for BoxedCloneSelectStatement<'_, ST, FromClause<QS>, DB, ()>
478where
479 QS: JoinTo<Rhs> + QuerySource,
480{
481 type FromClause = <QS as JoinTo<Rhs>>::FromClause;
482 type OnClause = QS::OnClause;
483
484 fn join_target(rhs: Rhs) -> (Self::FromClause, Self::OnClause) {
485 QS::join_target(rhs)
486 }
487}
488
489impl<ST, QS, DB, GB> QueryDsl for BoxedCloneSelectStatement<'_, ST, QS, DB, GB> {}
490
491impl<ST, QS, DB, GB> RunQueryDslSupport for BoxedCloneSelectStatement<'_, ST, QS, DB, GB> {}
492
493impl<ST, QS, DB, T, GB> Insertable<T> for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
494where
495 T: Table,
496 Self: Query,
497 <T::AllColumns as ValidGrouping<()>>::IsAggregate:
498 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
499{
500 type Values = InsertFromSelect<Self, T::AllColumns>;
501
502 fn values(self) -> Self::Values {
503 InsertFromSelect::new(self)
504 }
505}
506
507impl<ST, QS, DB, T, GB> Insertable<T> for &BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
508where
509 T: Table,
510 Self: Query,
511 <T::AllColumns as ValidGrouping<()>>::IsAggregate:
512 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
513{
514 type Values = InsertFromSelect<Self, T::AllColumns>;
515
516 fn values(self) -> Self::Values {
517 InsertFromSelect::new(self)
518 }
519}
520
521impl<'a, ST, QS, DB, GB> SelectNullableDsl for BoxedCloneSelectStatement<'a, ST, QS, DB, GB>
522where
523 ST: IntoNullable,
524{
525 type Output = BoxedCloneSelectStatement<'a, ST::Nullable, QS, DB>;
526
527 fn nullable(self) -> Self::Output {
528 BoxedCloneSelectStatement {
529 select: self.select,
530 from: self.from,
531 distinct: self.distinct,
532 where_clause: self.where_clause,
533 order: self.order,
534 limit_offset: self.limit_offset,
535 group_by: self.group_by,
536 having: self.having,
537 _marker: PhantomData,
538 }
539 }
540}
541
542impl<'a, ST, QS, DB, GB, Predicate> HavingDsl<Predicate>
543 for BoxedCloneSelectStatement<'a, ST, FromClause<QS>, DB, GB>
544where
545 QS: QuerySource,
546 DB: Backend,
547 GB: Expression,
548 HavingClause<Predicate>: QueryFragment<DB> + Send + Sync + 'a,
549 Predicate: AppearsOnTable<QS>,
550 Predicate::SqlType: BoolOrNullableBool,
551{
552 type Output = Self;
553
554 fn having(mut self, predicate: Predicate) -> Self::Output {
555 self.having = Arc::new(HavingClause(predicate));
556 self
557 }
558}
559
560impl<ST, QS, DB, GB> CombineDsl for BoxedCloneSelectStatement<'_, ST, QS, DB, GB>
561where
562 Self: Query,
563{
564 type Query = Self;
565
566 fn union<Rhs>(self, rhs: Rhs) -> crate::dsl::Union<Self, Rhs>
567 where
568 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
569 {
570 CombinationClause::new(Union, Distinct, self, rhs.as_query())
571 }
572
573 fn union_all<Rhs>(self, rhs: Rhs) -> crate::dsl::UnionAll<Self, Rhs>
574 where
575 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
576 {
577 CombinationClause::new(Union, All, self, rhs.as_query())
578 }
579
580 fn intersect<Rhs>(self, rhs: Rhs) -> crate::dsl::Intersect<Self, Rhs>
581 where
582 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
583 {
584 CombinationClause::new(Intersect, Distinct, self, rhs.as_query())
585 }
586
587 fn intersect_all<Rhs>(self, rhs: Rhs) -> crate::dsl::IntersectAll<Self, Rhs>
588 where
589 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
590 {
591 CombinationClause::new(Intersect, All, self, rhs.as_query())
592 }
593
594 fn except<Rhs>(self, rhs: Rhs) -> crate::dsl::Except<Self, Rhs>
595 where
596 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
597 {
598 CombinationClause::new(Except, Distinct, self, rhs.as_query())
599 }
600
601 fn except_all<Rhs>(self, rhs: Rhs) -> crate::dsl::ExceptAll<Self, Rhs>
602 where
603 Rhs: AsQuery<SqlType = <Self::Query as Query>::SqlType>,
604 {
605 CombinationClause::new(Except, All, self, rhs.as_query())
606 }
607}
608
609#[cfg(test)]
610mod tests {
611 use crate::prelude::*;
612
613 table! {
614 users {
615 id -> Integer,
616 }
617 }
618
619 fn assert_send<T>(_: T)
620 where
621 T: Send,
622 {
623 }
624
625 macro_rules! assert_boxed_query_send {
626 ($backend:ty) => {{
627 assert_send(users::table.into_boxed_clone::<$backend>());
628 assert_send(
629 users::table
630 .filter(users::id.eq(10))
631 .into_boxed_clone::<$backend>(),
632 );
633 };};
634 }
635
636 #[diesel_test_helper::test]
637 fn boxed_is_send() {
638 #[cfg(feature = "postgres")]
639 assert_boxed_query_send!(crate::pg::Pg);
640
641 #[cfg(feature = "__sqlite-shared")]
642 assert_boxed_query_send!(crate::sqlite::Sqlite);
643
644 #[cfg(feature = "mysql")]
645 assert_boxed_query_send!(crate::mysql::Mysql);
646
647 #[cfg(feature = "mariadb")]
648 assert_boxed_query_send!(crate::mariadb::Mariadb);
649 }
650}