diesel/expression/
operators.rs

1#[macro_export]
2#[doc(hidden)]
3macro_rules! __diesel_operator_body {
4    (
5        notation = $notation:ident,
6        struct_name = $name:ident,
7        operator = $operator:expr,
8        return_ty = (ReturnBasedOnArgs),
9        ty_params = ($($ty_param:ident,)+),
10        field_names = $field_names:tt,
11        backend_ty_params = $backend_ty_params:tt,
12        backend_ty = $backend_ty:ty,
13    ) => {
14        $crate::__diesel_operator_body! {
15            notation = $notation,
16            struct_name = $name,
17            operator = $operator,
18            return_ty = (ST),
19            ty_params = ($($ty_param,)+),
20            field_names = $field_names,
21            backend_ty_params = $backend_ty_params,
22            backend_ty = $backend_ty,
23            expression_ty_params = (ST,),
24            expression_bounds = ($($ty_param: $crate::expression::Expression<SqlType = ST>,)+),
25        }
26    };
27
28    (
29        notation = $notation:ident,
30        struct_name = $name:ident,
31        operator = $operator:expr,
32        return_ty = ($($return_ty:tt)+),
33        ty_params = ($($ty_param:ident,)+),
34        field_names = $field_names:tt,
35        backend_ty_params = $backend_ty_params:tt,
36        backend_ty = $backend_ty:ty,
37    ) => {
38        $crate::__diesel_operator_body! {
39            notation = $notation,
40            struct_name = $name,
41            operator = $operator,
42            return_ty = ($($return_ty)*),
43            ty_params = ($($ty_param,)+),
44            field_names = $field_names,
45            backend_ty_params = $backend_ty_params,
46            backend_ty = $backend_ty,
47            expression_ty_params = (),
48            expression_bounds = ($($ty_param: $crate::expression::Expression,)+),
49        }
50    };
51
52    (
53        notation = $notation:ident,
54        struct_name = $name:ident,
55        operator = $operator:expr,
56        return_ty = ($($return_ty:tt)+),
57        ty_params = ($($ty_param:ident,)+),
58        field_names = ($($field_name:ident,)+),
59        backend_ty_params = ($($backend_ty_param:ident,)*),
60        backend_ty = $backend_ty:ty,
61        expression_ty_params = ($($expression_ty_params:ident,)*),
62        expression_bounds = ($($expression_bounds:tt)*),
63    ) => {
64        #[derive(
65            Debug,
66            Clone,
67            Copy,
68            $crate::query_builder::QueryId,
69            $crate::sql_types::DieselNumericOps,
70            $crate::expression::ValidGrouping
71        )]
72        #[doc(hidden)]
73        pub struct $name<$($ty_param,)+> {
74            $(pub(crate) $field_name: $ty_param,)+
75        }
76
77        impl<$($ty_param,)+> $name<$($ty_param,)+> {
78            pub(crate) fn new($($field_name: $ty_param,)+) -> Self {
79                $name { $($field_name,)+ }
80            }
81        }
82
83        $crate::impl_selectable_expression!($name<$($ty_param),+>);
84
85        impl<$($ty_param,)+ $($expression_ty_params,)*> $crate::expression::Expression for $name<$($ty_param,)+> where
86            $($expression_bounds)*
87        {
88            type SqlType = $($return_ty)*;
89        }
90
91        impl<$($ty_param,)+ $($backend_ty_param,)*> $crate::query_builder::QueryFragment<$backend_ty>
92            for $name<$($ty_param,)+> where
93                $($ty_param: $crate::query_builder::QueryFragment<$backend_ty>,)+
94                $($backend_ty_param: $crate::backend::Backend,)*
95        {
96            fn walk_ast<'b>(
97                &'b self,
98                mut out: $crate::query_builder::AstPass<'_, 'b, $backend_ty>
99            ) -> $crate::result::QueryResult<()>
100            {
101                $crate::__diesel_operator_to_sql!(
102                    notation = $notation,
103                    operator_expr = out.push_sql($operator),
104                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
105                );
106                Ok(())
107            }
108        }
109
110        impl<S, $($ty_param,)+> $crate::internal::operators_macro::FieldAliasMapper<S> for $name<$($ty_param,)+>
111        where
112            S: $crate::query_source::AliasSource,
113            $($ty_param: $crate::internal::operators_macro::FieldAliasMapper<S>,)+
114        {
115            type Out = $name<
116                $(<$ty_param as $crate::internal::operators_macro::FieldAliasMapper<S>>::Out,)+
117            >;
118            fn map(self, alias: &$crate::query_source::Alias<S>) -> Self::Out {
119                $name {
120                    $($field_name: self.$field_name.map(alias),)+
121                }
122            }
123        }
124    }
125}
126
127#[macro_export]
128#[doc(hidden)]
129macro_rules! __diesel_operator_to_sql {
130    (
131        notation = infix,
132        operator_expr = $op:expr,
133        field_exprs = ($left:expr, $right:expr),
134    ) => {
135        $left;
136        $op;
137        $right;
138    };
139
140    (
141        notation = postfix,
142        operator_expr = $op:expr,
143        field_exprs = ($expr:expr),
144    ) => {
145        $expr;
146        $op;
147    };
148
149    (
150        notation = prefix,
151        operator_expr = $op:expr,
152        field_exprs = ($expr:expr),
153    ) => {
154        $op;
155        $expr;
156    };
157}
158
159/// Useful for libraries adding support for new SQL types. Apps should never
160/// need to call this.
161///
162/// This will create a new type with the given name. It will implement all
163/// methods needed to be used as an expression in Diesel, placing the given
164/// SQL between the two elements. The third argument specifies the SQL type
165/// that the operator returns. If it is not given, the type will be assumed
166/// to be `Bool`.
167///
168/// If the operator is specific to a single backend, you can specify this by
169/// adding `backend: Pg` or similar as the last argument.
170///
171/// It should be noted that the generated impls will not constrain the SQL
172/// types of the arguments. You should ensure that they are of the right
173/// type in your function which constructs the operator.
174///
175/// Typically you would not expose the type that this generates directly. You'd
176/// expose a function (or trait) used to construct the expression, and a helper
177/// type which represents the return type of that function. See the source of
178/// `diesel::expression::expression_methods` and
179/// `diesel::expression::helper_types` for real world examples of this.
180///
181/// # Examples
182///
183/// # Possible invocations
184///
185/// ```ignore
186/// // The SQL type will be boolean. The backend will not be constrained
187/// infix_operator!(Matches, " @@ ");
188///
189/// // Queries which try to execute `Contains` on a backend other than Pg
190/// // will fail to compile
191/// infix_operator!(Contains, " @> ", backend: Pg);
192///
193/// // The type of `Concat` will be `TsVector` rather than Bool
194/// infix_operator!(Concat, " || ", TsVector);
195///
196/// // It is perfectly fine to have multiple operators with the same SQL.
197/// // Diesel will ensure that the queries are always unambiguous in which
198/// // operator applies
199/// infix_operator!(Or, " || ", TsQuery);
200///
201/// // Specifying both the return types and the backend
202/// infix_operator!(And, " && ", TsQuery, backend: Pg);
203/// ```
204///
205/// ## Example usage
206///
207/// ```rust
208/// # include!("../doctest_setup.rs");
209/// # use diesel::sql_types::SqlType;
210/// # use diesel::expression::TypedExpressionType;
211/// #
212/// # fn main() {
213/// #     use schema::users::dsl::*;
214/// #     let connection = &mut establish_connection();
215/// diesel::infix_operator!(MyEq, " = ");
216///
217/// use diesel::expression::AsExpression;
218///
219/// // Normally you would put this on a trait instead
220/// fn my_eq<T, U, ST>(left: T, right: U) -> MyEq<T, U::Expression> where
221///     T: Expression<SqlType = ST>,
222///     U: AsExpression<ST>,
223///     ST: SqlType + TypedExpressionType,
224/// {
225///     MyEq::new(left, right.as_expression())
226/// }
227///
228/// let users_with_name = users.select(id).filter(my_eq(name, "Sean"));
229///
230/// assert_eq!(Ok(1), users_with_name.first(connection));
231/// # }
232/// ```
233#[macro_export]
234macro_rules! infix_operator {
235    ($name:ident, $operator:expr) => {
236        $crate::infix_operator!($name, $operator, $crate::sql_types::Bool);
237    };
238
239    ($name:ident, $operator:expr, backend: $backend:ty) => {
240        $crate::infix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
241    };
242
243    ($name:ident, $operator:expr, $($return_ty:tt)::*) => {
244        $crate::__diesel_infix_operator!(
245            name = $name,
246            operator = $operator,
247            return_ty = NullableBasedOnArgs ($($return_ty)::*),
248            backend_ty_params = (DB,),
249            backend_ty = DB,
250        );
251    };
252
253    ($name:ident, $operator:expr, $($return_ty:tt)::*, backend: $backend:ty) => {
254        $crate::__diesel_infix_operator!(
255            name = $name,
256            operator = $operator,
257            return_ty = NullableBasedOnArgs ($($return_ty)::*),
258            backend_ty_params = (),
259            backend_ty = $backend,
260        );
261    };
262
263}
264#[macro_export]
265#[doc(hidden)]
266macro_rules! __diesel_infix_operator {
267    ($name:ident, $operator:expr, ConstantNullability $($return_ty:tt)::*) => {
268        $crate::__diesel_infix_operator!(
269            name = $name,
270            operator = $operator,
271            return_ty = ($($return_ty)::*),
272            backend_ty_params = (DB,),
273            backend_ty = DB,
274        );
275    };
276    ($name:ident, $operator:expr, __diesel_internal_SameResultAsInput, backend: $backend:ty) => {
277        $crate::__diesel_infix_operator!(
278            name = $name,
279            operator = $operator,
280            return_ty = (<T as $crate::expression::Expression>::SqlType),
281            backend_ty_params = (),
282            backend_ty = $backend,
283        );
284    };
285    ($name:ident, $operator:expr, ConstantNullability $($return_ty:tt)::*, backend: $backend:ty) => {
286        $crate::__diesel_infix_operator!(
287            name = $name,
288            operator = $operator,
289            return_ty = ($($return_ty)::*),
290            backend_ty_params = (),
291            backend_ty = $backend,
292        );
293    };
294
295    (
296        name = $name:ident,
297        operator = $operator:expr,
298        return_ty = NullableBasedOnArgs ($($return_ty:tt)+),
299        backend_ty_params = $backend_ty_params:tt,
300        backend_ty = $backend_ty:ty,
301    ) => {
302        $crate::__diesel_infix_operator!(
303            name = $name,
304            operator = $operator,
305            return_ty = (
306                $crate::sql_types::is_nullable::MaybeNullable<
307                    $crate::sql_types::is_nullable::IsOneNullable<
308                        <T as $crate::expression::Expression>::SqlType,
309                        <U as $crate::expression::Expression>::SqlType
310                    >,
311                    $($return_ty)+
312                >
313            ),
314            expression_bounds = (
315                $crate::sql_types::is_nullable::IsSqlTypeNullable<
316                    <T as $crate::expression::Expression>::SqlType
317                >: $crate::sql_types::OneIsNullable<
318                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
319                        <U as $crate::expression::Expression>::SqlType
320                    >
321                >,
322                $crate::sql_types::is_nullable::IsOneNullable<
323                    <T as $crate::expression::Expression>::SqlType,
324                    <U as $crate::expression::Expression>::SqlType
325                >: $crate::sql_types::MaybeNullableType<$($return_ty)+>,
326            ),
327            backend_ty_params = $backend_ty_params,
328            backend_ty = $backend_ty,
329        );
330    };
331
332    (
333        name = $name:ident,
334        operator = $operator:expr,
335        return_ty = ($($return_ty:tt)+),
336        backend_ty_params = $backend_ty_params:tt,
337        backend_ty = $backend_ty:ty,
338    ) => {
339        $crate::__diesel_infix_operator!(
340            name = $name,
341            operator = $operator,
342            return_ty = ($($return_ty)+),
343            expression_bounds = (),
344            backend_ty_params = $backend_ty_params,
345            backend_ty = $backend_ty,
346        );
347    };
348
349    (
350        name = $name:ident,
351        operator = $operator:expr,
352        return_ty = ($($return_ty:tt)+),
353        expression_bounds = ($($expression_bounds:tt)*),
354        backend_ty_params = $backend_ty_params:tt,
355        backend_ty = $backend_ty:ty,
356    ) => {
357        $crate::__diesel_operator_body!(
358            notation = infix,
359            struct_name = $name,
360            operator = $operator,
361            return_ty = ($($return_ty)+),
362            ty_params = (T, U,),
363            field_names = (left, right,),
364            backend_ty_params = $backend_ty_params,
365            backend_ty = $backend_ty,
366            expression_ty_params = (),
367            expression_bounds = (
368                T: $crate::expression::Expression,
369                U: $crate::expression::Expression,
370                <T as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
371                <U as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
372                $($expression_bounds)*
373            ),
374        );
375    };
376}
377
378#[macro_export]
379#[deprecated(since = "2.0.0", note = "use `diesel::infix_operator!` instead")]
380#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
381#[doc(hidden)]
382macro_rules! diesel_infix_operator {
383    ($($args:tt)*) => {
384        $crate::infix_operator!($($args)*);
385    }
386}
387
388/// Useful for libraries adding support for new SQL types. Apps should never
389/// need to call this.
390///
391/// Similar to [`infix_operator!`], but the generated type will only take
392/// a single argument rather than two. The operator SQL will be placed after
393/// the single argument. See [`infix_operator!`] for example usage.
394///
395#[macro_export]
396macro_rules! postfix_operator {
397    ($name:ident, $operator:expr) => {
398        $crate::postfix_operator!($name, $operator, $crate::sql_types::Bool);
399    };
400
401    ($name:ident, $operator:expr, backend: $backend:ty) => {
402        $crate::postfix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
403    };
404
405    ($name:ident, $operator:expr, ConditionalNullability $($return_ty:tt)::*) => {
406        $crate::postfix_operator!(
407            name = $name,
408            operator = $operator,
409            return_ty = NullableBasedOnArgs ($($return_ty)::*),
410        );
411    };
412
413    ($name:ident, $operator:expr, ConditionalNullability $($return_ty:tt)::*, backend: $backend:ty) => {
414        $crate::postfix_operator!(
415            $name,
416            $operator,
417            return_ty = NullableBasedOnArgs ($($return_ty)::*),
418            backend: $backend
419        );
420    };
421
422    ($name:ident, $operator:expr, return_ty = NullableBasedOnArgs($return_ty:ty)) => {
423        $crate::__diesel_operator_body!(
424            notation = postfix,
425            struct_name = $name,
426            operator = $operator,
427            return_ty = (
428                $crate::sql_types::is_nullable::MaybeNullable<
429                    <<Expr as $crate::expression::Expression>::SqlType as $crate::sql_types::SqlType>::IsNull,
430                    $return_ty
431                >
432            ),
433            ty_params = (Expr,),
434            field_names = (expr,),
435            backend_ty_params = (DB,),
436            backend_ty = DB,
437            expression_ty_params = (),
438            expression_bounds = (
439                Expr: $crate::expression::Expression,
440                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
441                $crate::sql_types::is_nullable::IsOneNullable<
442                    <Expr as $crate::expression::Expression>::SqlType,
443                    $return_ty
444                >: $crate::sql_types::MaybeNullableType<$return_ty>,
445            ),
446        );
447    };
448
449    ($name:ident, $operator:expr, return_ty = NullableBasedOnArgs($return_ty:ty), backend: $backend:ty) => {
450        $crate::__diesel_operator_body!(
451            notation = postfix,
452            struct_name = $name,
453            operator = $operator,
454            return_ty = (
455                $crate::sql_types::is_nullable::MaybeNullable<
456                    $crate::sql_types::is_nullable::IsOneNullable<
457                        <Expr as $crate::expression::Expression>::SqlType,
458                        $return_ty
459                    >,
460                    $return_ty
461                >
462            ),
463            ty_params = (Expr,),
464            field_names = (expr,),
465            backend_ty_params = (),
466            backend_ty = $backend,
467            expression_ty_params = (),
468            expression_bounds = (
469                Expr: $crate::expression::Expression,
470                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
471                $crate::sql_types::is_nullable::IsOneNullable<
472                    <Expr as $crate::expression::Expression>::SqlType,
473                    $return_ty
474                >: $crate::sql_types::MaybeNullableType<$return_ty>,
475            ),
476        );
477    };
478
479    ($name:ident, $operator:expr, $return_ty:ty) => {
480        $crate::__diesel_operator_body!(
481            notation = postfix,
482            struct_name = $name,
483            operator = $operator,
484            return_ty = ($return_ty),
485            ty_params = (Expr,),
486            field_names = (expr,),
487            backend_ty_params = (DB,),
488            backend_ty = DB,
489        );
490    };
491
492    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
493        $crate::__diesel_operator_body!(
494            notation = postfix,
495            struct_name = $name,
496            operator = $operator,
497            return_ty = ($return_ty),
498            ty_params = (Expr,),
499            field_names = (expr,),
500            backend_ty_params = (),
501            backend_ty = $backend,
502        );
503    };
504}
505
506#[macro_export]
507#[deprecated(since = "2.0.0", note = "use `diesel::postfix_operator!` instead")]
508#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
509#[doc(hidden)]
510macro_rules! diesel_postfix_operator {
511    ($($args:tt)*) => {
512        $crate::postfix_operator!($($args)*);
513    }
514}
515
516/// Useful for libraries adding support for new SQL types. Apps should never
517/// need to call this.
518///
519/// Similar to [`infix_operator!`], but the generated type will only take
520/// a single argument rather than two. The operator SQL will be placed before
521/// the single argument. See [`infix_operator!`] for example usage.
522///
523#[macro_export]
524macro_rules! prefix_operator {
525    ($name:ident, $operator:expr) => {
526        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool);
527    };
528
529    ($name:ident, $operator:expr, backend: $backend:ty) => {
530        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
531    };
532
533    ($name:ident, $operator:expr, $return_ty:ty) => {
534        $crate::__diesel_operator_body!(
535            notation = prefix,
536            struct_name = $name,
537            operator = $operator,
538            return_ty = (
539                $crate::sql_types::is_nullable::MaybeNullable<
540                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
541                        <Expr as $crate::expression::Expression>::SqlType
542                    >,
543                    $return_ty,
544                >
545            ),
546            ty_params = (Expr,),
547            field_names = (expr,),
548            backend_ty_params = (DB,),
549            backend_ty = DB,
550            expression_ty_params = (),
551            expression_bounds = (
552                Expr: $crate::expression::Expression,
553                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
554                $crate::sql_types::is_nullable::IsSqlTypeNullable<
555                    <Expr as $crate::expression::Expression>::SqlType
556                >: $crate::sql_types::MaybeNullableType<$return_ty>,
557            ),
558        );
559    };
560
561    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
562        $crate::__diesel_operator_body!(
563            notation = prefix,
564            struct_name = $name,
565            operator = $operator,
566            return_ty = (
567                $crate::sql_types::is_nullable::MaybeNullable<
568                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
569                        <Expr as $crate::expression::Expression>::SqlType
570                    >,
571                    $return_ty,
572                >
573            ),
574            ty_params = (Expr,),
575            field_names = (expr,),
576            backend_ty_params = (),
577            backend_ty = $backend,
578            expression_ty_params = (),
579            expression_bounds = (
580                Expr: $crate::expression::Expression,
581                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
582                $crate::sql_types::is_nullable::IsSqlTypeNullable<
583                    <Expr as $crate::expression::Expression>::SqlType
584                >: $crate::sql_types::MaybeNullableType<$return_ty>,
585            ),
586        );
587    };
588}
589
590#[macro_export]
591#[deprecated(since = "2.0.0", note = "use `diesel::prefix_operator!` instead")]
592#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
593#[doc(hidden)]
594macro_rules! diesel_prefix_operator {
595    ($($args:tt)*) => {
596        $crate::prefix_operator!($($args)*);
597    }
598}
599
600infix_operator!(And, " AND ");
601infix_operator!(Or, " OR ");
602infix_operator!(Escape, " ESCAPE ");
603infix_operator!(Eq, " = ");
604infix_operator!(Gt, " > ");
605infix_operator!(GtEq, " >= ");
606infix_operator!(Lt, " < ");
607infix_operator!(LtEq, " <= ");
608infix_operator!(NotEq, " != ");
609infix_operator!(NotLike, " NOT LIKE ");
610infix_operator!(Between, " BETWEEN ");
611infix_operator!(NotBetween, " NOT BETWEEN ");
612
613postfix_operator!(IsNull, " IS NULL");
614postfix_operator!(IsNotNull, " IS NOT NULL");
615postfix_operator!(
616    Asc,
617    " ASC",
618    crate::expression::expression_types::NotSelectable
619);
620postfix_operator!(
621    Desc,
622    " DESC",
623    crate::expression::expression_types::NotSelectable
624);
625
626prefix_operator!(Not, " NOT ");
627
628use crate::backend::{sql_dialect, Backend, SqlDialect};
629use crate::expression::{TypedExpressionType, ValidGrouping};
630use crate::insertable::{ColumnInsertValue, Insertable};
631use crate::query_builder::{QueryFragment, QueryId, ValuesClause};
632use crate::query_source::Column;
633use crate::sql_types::{DieselNumericOps, SqlType};
634
635impl<T, U> Insertable<T::Table> for Eq<T, U>
636where
637    T: Column,
638{
639    type Values = ValuesClause<ColumnInsertValue<T, U>, T::Table>;
640
641    fn values(self) -> Self::Values {
642        ValuesClause::new(ColumnInsertValue::new(self.right))
643    }
644}
645
646impl<'a, T, Tab, U> Insertable<Tab> for &'a Eq<T, U>
647where
648    T: Copy,
649    Eq<T, &'a U>: Insertable<Tab>,
650{
651    type Values = <Eq<T, &'a U> as Insertable<Tab>>::Values;
652
653    fn values(self) -> Self::Values {
654        Eq::new(self.left, &self.right).values()
655    }
656}
657
658/// This type represents a string concat operator
659#[diesel_derives::__diesel_public_if(
660    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
661    public_fields(left, right)
662)]
663#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
664pub struct Concat<L, R> {
665    /// The left side expression of the operator
666    pub(crate) left: L,
667    /// The right side expression of the operator
668    pub(crate) right: R,
669}
670
671impl<L, R> Concat<L, R> {
672    pub(crate) fn new(left: L, right: R) -> Self {
673        Self { left, right }
674    }
675}
676
677impl<L, R, ST> crate::expression::Expression for Concat<L, R>
678where
679    L: crate::expression::Expression<SqlType = ST>,
680    R: crate::expression::Expression<SqlType = ST>,
681    ST: SqlType + TypedExpressionType,
682{
683    type SqlType = ST;
684}
685
686impl_selectable_expression!(Concat<L, R>);
687
688impl<L, R, DB> QueryFragment<DB> for Concat<L, R>
689where
690    DB: Backend,
691    Self: QueryFragment<DB, DB::ConcatClause>,
692{
693    fn walk_ast<'b>(
694        &'b self,
695        pass: crate::query_builder::AstPass<'_, 'b, DB>,
696    ) -> crate::result::QueryResult<()> {
697        <Self as QueryFragment<DB, DB::ConcatClause>>::walk_ast(self, pass)
698    }
699}
700
701impl<L, R, DB> QueryFragment<DB, sql_dialect::concat_clause::ConcatWithPipesClause> for Concat<L, R>
702where
703    L: QueryFragment<DB>,
704    R: QueryFragment<DB>,
705    DB: Backend + SqlDialect<ConcatClause = sql_dialect::concat_clause::ConcatWithPipesClause>,
706{
707    fn walk_ast<'b>(
708        &'b self,
709        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
710    ) -> crate::result::QueryResult<()> {
711        // Since popular MySQL scalability layer Vitess does not support pipes in query parsing
712        // CONCAT has been implemented separately for MySQL (see MysqlConcatClause)
713        out.push_sql("(");
714        self.left.walk_ast(out.reborrow())?;
715        out.push_sql(" || ");
716        self.right.walk_ast(out.reborrow())?;
717        out.push_sql(")");
718        Ok(())
719    }
720}
721
722// need an explicit impl here to control which types are allowed
723#[derive(
724    Debug,
725    Clone,
726    Copy,
727    crate::query_builder::QueryId,
728    crate::sql_types::DieselNumericOps,
729    crate::expression::ValidGrouping,
730)]
731#[doc(hidden)]
732pub struct Like<T, U> {
733    pub(crate) left: T,
734    pub(crate) right: U,
735}
736
737impl<T, U> Like<T, U> {
738    pub(crate) fn new(left: T, right: U) -> Self {
739        Like { left, right }
740    }
741}
742
743impl<T, U, QS> crate::expression::SelectableExpression<QS> for Like<T, U>
744where
745    Like<T, U>: crate::expression::AppearsOnTable<QS>,
746    T: crate::expression::SelectableExpression<QS>,
747    U: crate::expression::SelectableExpression<QS>,
748{
749}
750
751impl<T, U, QS> crate::expression::AppearsOnTable<QS> for Like<T, U>
752where
753    Like<T, U>: crate::expression::Expression,
754    T: crate::expression::AppearsOnTable<QS>,
755    U: crate::expression::AppearsOnTable<QS>,
756{
757}
758
759impl<T, U> crate::expression::Expression for Like<T, U>
760where
761    T: crate::expression::Expression,
762    U: crate::expression::Expression,
763    <T as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
764    <U as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
765    crate::sql_types::is_nullable::IsSqlTypeNullable<<T as crate::expression::Expression>::SqlType>:
766        crate::sql_types::OneIsNullable<
767            crate::sql_types::is_nullable::IsSqlTypeNullable<
768                <U as crate::expression::Expression>::SqlType,
769            >,
770        >,
771    crate::sql_types::is_nullable::IsOneNullable<
772        <T as crate::expression::Expression>::SqlType,
773        <U as crate::expression::Expression>::SqlType,
774    >: crate::sql_types::MaybeNullableType<crate::sql_types::Bool>,
775{
776    type SqlType = crate::sql_types::is_nullable::MaybeNullable<
777        crate::sql_types::is_nullable::IsOneNullable<
778            <T as crate::expression::Expression>::SqlType,
779            <U as crate::expression::Expression>::SqlType,
780        >,
781        crate::sql_types::Bool,
782    >;
783}
784
785impl<T, U, DB> crate::query_builder::QueryFragment<DB> for Like<T, U>
786where
787    T: crate::query_builder::QueryFragment<DB> + crate::Expression,
788    U: crate::query_builder::QueryFragment<DB>,
789    DB: crate::backend::Backend,
790    DB: LikeIsAllowedForType<T::SqlType>,
791{
792    fn walk_ast<'b>(
793        &'b self,
794        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
795    ) -> crate::result::QueryResult<()> {
796        (self.left.walk_ast(out.reborrow())?);
797        (out.push_sql(" LIKE "));
798        (self.right.walk_ast(out.reborrow())?);
799        Ok(())
800    }
801}
802
803impl<S, T, U> crate::internal::operators_macro::FieldAliasMapper<S> for Like<T, U>
804where
805    S: crate::query_source::AliasSource,
806    T: crate::internal::operators_macro::FieldAliasMapper<S>,
807    U: crate::internal::operators_macro::FieldAliasMapper<S>,
808{
809    type Out = Like<
810        <T as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
811        <U as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
812    >;
813    fn map(self, alias: &crate::query_source::Alias<S>) -> Self::Out {
814        Like {
815            left: self.left.map(alias),
816            right: self.right.map(alias),
817        }
818    }
819}
820
821#[diagnostic::on_unimplemented(
822    message = "Cannot use the `LIKE` operator with expressions of the type `{ST}` for the backend `{Self}`",
823    note = "Expressions of the type `diesel::sql_types::Text` and `diesel::sql_types::Nullable<Text>` are \n\
824            allowed for all backends"
825)]
826#[cfg_attr(
827    feature = "postgres_backend",
828    diagnostic::on_unimplemented(
829        note = "Expressions of the type `diesel::sql_types::Binary` and `diesel::sql_types::Nullable<Binary>` are \n\
830            allowed for the PostgreSQL backend"
831    )
832)]
833pub trait LikeIsAllowedForType<ST>: Backend {}
834
835impl<DB> LikeIsAllowedForType<crate::sql_types::Text> for DB where DB: Backend {}
836
837#[cfg(feature = "postgres_backend")]
838impl LikeIsAllowedForType<crate::pg::sql_types::Citext> for crate::pg::Pg {}
839
840impl<T, DB> LikeIsAllowedForType<crate::sql_types::Nullable<T>> for DB where
841    DB: Backend + LikeIsAllowedForType<T>
842{
843}