Skip to main content

diesel/query_builder/select_statement/
boxed_clone.rs

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// This is used by the table macro internally
27/// This type represents a boxed select query
28///
29/// Using this type directly is only meaningful for custom backends
30/// that need to provide a custom [`QueryFragment`] implementation
31#[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    /// The select clause of the query
47    select: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
48    /// The from clause of the query
49    from: QS,
50    /// The distinct clause of the query
51    distinct: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
52    /// The where clause of the query
53    where_clause: BoxedCloneWhereClause<'a, DB>,
54    /// The order clause of the query
55    order: Option<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>>,
56    /// The combined limit/offset clause of the query
57    limit_offset: BoxedCloneLimitOffsetClause<'a, DB>,
58    /// The group by clause of the query
59    group_by: Arc<dyn QueryFragment<DB> + Send + Sync + 'a>,
60    /// The having clause of the query
61    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// that's a trait to control who can access these methods
154#[doc(hidden)] // exported via internal::derives::multiconnection
155pub 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
225// Boxing and every boxed clause method only accept expressions of `QS`, so a boxed
226// statement never references the outer query
227impl<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    /// The statement with `select` as its select clause and every other clause kept.
305    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
443// no impls for `NoFromClause` here because order is not really supported there yet
444impl<'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}