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, $return_ty:ty) => {
406        $crate::__diesel_operator_body!(
407            notation = postfix,
408            struct_name = $name,
409            operator = $operator,
410            return_ty = ($return_ty),
411            ty_params = (Expr,),
412            field_names = (expr,),
413            backend_ty_params = (DB,),
414            backend_ty = DB,
415        );
416    };
417
418    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
419        $crate::__diesel_operator_body!(
420            notation = postfix,
421            struct_name = $name,
422            operator = $operator,
423            return_ty = ($return_ty),
424            ty_params = (Expr,),
425            field_names = (expr,),
426            backend_ty_params = (),
427            backend_ty = $backend,
428        );
429    };
430}
431
432#[macro_export]
433#[deprecated(since = "2.0.0", note = "use `diesel::postfix_operator!` instead")]
434#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
435#[doc(hidden)]
436macro_rules! diesel_postfix_operator {
437    ($($args:tt)*) => {
438        $crate::postfix_operator!($($args)*);
439    }
440}
441
442/// Useful for libraries adding support for new SQL types. Apps should never
443/// need to call this.
444///
445/// Similar to [`infix_operator!`], but the generated type will only take
446/// a single argument rather than two. The operator SQL will be placed before
447/// the single argument. See [`infix_operator!`] for example usage.
448///
449#[macro_export]
450macro_rules! prefix_operator {
451    ($name:ident, $operator:expr) => {
452        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool);
453    };
454
455    ($name:ident, $operator:expr, backend: $backend:ty) => {
456        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
457    };
458
459    ($name:ident, $operator:expr, $return_ty:ty) => {
460        $crate::__diesel_operator_body!(
461            notation = prefix,
462            struct_name = $name,
463            operator = $operator,
464            return_ty = (
465                $crate::sql_types::is_nullable::MaybeNullable<
466                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
467                        <Expr as $crate::expression::Expression>::SqlType
468                    >,
469                    $return_ty,
470                >
471            ),
472            ty_params = (Expr,),
473            field_names = (expr,),
474            backend_ty_params = (DB,),
475            backend_ty = DB,
476            expression_ty_params = (),
477            expression_bounds = (
478                Expr: $crate::expression::Expression,
479                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
480                $crate::sql_types::is_nullable::IsSqlTypeNullable<
481                    <Expr as $crate::expression::Expression>::SqlType
482                >: $crate::sql_types::MaybeNullableType<$return_ty>,
483            ),
484        );
485    };
486
487    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
488        $crate::__diesel_operator_body!(
489            notation = prefix,
490            struct_name = $name,
491            operator = $operator,
492            return_ty = (
493                $crate::sql_types::is_nullable::MaybeNullable<
494                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
495                        <Expr as $crate::expression::Expression>::SqlType
496                    >,
497                    $return_ty,
498                >
499            ),
500            ty_params = (Expr,),
501            field_names = (expr,),
502            backend_ty_params = (),
503            backend_ty = $backend,
504            expression_ty_params = (),
505            expression_bounds = (
506                Expr: $crate::expression::Expression,
507                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
508                $crate::sql_types::is_nullable::IsSqlTypeNullable<
509                    <Expr as $crate::expression::Expression>::SqlType
510                >: $crate::sql_types::MaybeNullableType<$return_ty>,
511            ),
512        );
513    };
514}
515
516#[macro_export]
517#[deprecated(since = "2.0.0", note = "use `diesel::prefix_operator!` instead")]
518#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
519#[doc(hidden)]
520macro_rules! diesel_prefix_operator {
521    ($($args:tt)*) => {
522        $crate::prefix_operator!($($args)*);
523    }
524}
525
526infix_operator!(And, " AND ");
527infix_operator!(Or, " OR ");
528infix_operator!(Escape, " ESCAPE ");
529infix_operator!(Eq, " = ");
530infix_operator!(Gt, " > ");
531infix_operator!(GtEq, " >= ");
532infix_operator!(Lt, " < ");
533infix_operator!(LtEq, " <= ");
534infix_operator!(NotEq, " != ");
535infix_operator!(NotLike, " NOT LIKE ");
536infix_operator!(Between, " BETWEEN ");
537infix_operator!(NotBetween, " NOT BETWEEN ");
538
539postfix_operator!(IsNull, " IS NULL");
540postfix_operator!(IsNotNull, " IS NOT NULL");
541postfix_operator!(
542    Asc,
543    " ASC",
544    crate::expression::expression_types::NotSelectable
545);
546postfix_operator!(
547    Desc,
548    " DESC",
549    crate::expression::expression_types::NotSelectable
550);
551
552prefix_operator!(Not, " NOT ");
553
554use crate::backend::{sql_dialect, Backend, SqlDialect};
555use crate::expression::{TypedExpressionType, ValidGrouping};
556use crate::insertable::{ColumnInsertValue, Insertable};
557use crate::query_builder::{QueryFragment, QueryId, ValuesClause};
558use crate::query_source::Column;
559use crate::sql_types::{DieselNumericOps, SqlType};
560
561impl<T, U> Insertable<T::Table> for Eq<T, U>
562where
563    T: Column,
564{
565    type Values = ValuesClause<ColumnInsertValue<T, U>, T::Table>;
566
567    fn values(self) -> Self::Values {
568        ValuesClause::new(ColumnInsertValue::new(self.right))
569    }
570}
571
572impl<'a, T, Tab, U> Insertable<Tab> for &'a Eq<T, U>
573where
574    T: Copy,
575    Eq<T, &'a U>: Insertable<Tab>,
576{
577    type Values = <Eq<T, &'a U> as Insertable<Tab>>::Values;
578
579    fn values(self) -> Self::Values {
580        Eq::new(self.left, &self.right).values()
581    }
582}
583
584/// This type represents a string concat operator
585#[diesel_derives::__diesel_public_if(
586    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
587    public_fields(left, right)
588)]
589#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
590pub struct Concat<L, R> {
591    /// The left side expression of the operator
592    pub(crate) left: L,
593    /// The right side expression of the operator
594    pub(crate) right: R,
595}
596
597impl<L, R> Concat<L, R> {
598    pub(crate) fn new(left: L, right: R) -> Self {
599        Self { left, right }
600    }
601}
602
603impl<L, R, ST> crate::expression::Expression for Concat<L, R>
604where
605    L: crate::expression::Expression<SqlType = ST>,
606    R: crate::expression::Expression<SqlType = ST>,
607    ST: SqlType + TypedExpressionType,
608{
609    type SqlType = ST;
610}
611
612impl_selectable_expression!(Concat<L, R>);
613
614impl<L, R, DB> QueryFragment<DB> for Concat<L, R>
615where
616    DB: Backend,
617    Self: QueryFragment<DB, DB::ConcatClause>,
618{
619    fn walk_ast<'b>(
620        &'b self,
621        pass: crate::query_builder::AstPass<'_, 'b, DB>,
622    ) -> crate::result::QueryResult<()> {
623        <Self as QueryFragment<DB, DB::ConcatClause>>::walk_ast(self, pass)
624    }
625}
626
627impl<L, R, DB> QueryFragment<DB, sql_dialect::concat_clause::ConcatWithPipesClause> for Concat<L, R>
628where
629    L: QueryFragment<DB>,
630    R: QueryFragment<DB>,
631    DB: Backend + SqlDialect<ConcatClause = sql_dialect::concat_clause::ConcatWithPipesClause>,
632{
633    fn walk_ast<'b>(
634        &'b self,
635        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
636    ) -> crate::result::QueryResult<()> {
637        // Since popular MySQL scalability layer Vitess does not support pipes in query parsing
638        // CONCAT has been implemented separately for MySQL (see MysqlConcatClause)
639        out.push_sql("(");
640        self.left.walk_ast(out.reborrow())?;
641        out.push_sql(" || ");
642        self.right.walk_ast(out.reborrow())?;
643        out.push_sql(")");
644        Ok(())
645    }
646}
647
648// need an explicit impl here to control which types are allowed
649#[derive(
650    Debug,
651    Clone,
652    Copy,
653    crate::query_builder::QueryId,
654    crate::sql_types::DieselNumericOps,
655    crate::expression::ValidGrouping,
656)]
657#[doc(hidden)]
658pub struct Like<T, U> {
659    pub(crate) left: T,
660    pub(crate) right: U,
661}
662
663impl<T, U> Like<T, U> {
664    pub(crate) fn new(left: T, right: U) -> Self {
665        Like { left, right }
666    }
667}
668
669impl<T, U, QS> crate::expression::SelectableExpression<QS> for Like<T, U>
670where
671    Like<T, U>: crate::expression::AppearsOnTable<QS>,
672    T: crate::expression::SelectableExpression<QS>,
673    U: crate::expression::SelectableExpression<QS>,
674{
675}
676
677impl<T, U, QS> crate::expression::AppearsOnTable<QS> for Like<T, U>
678where
679    Like<T, U>: crate::expression::Expression,
680    T: crate::expression::AppearsOnTable<QS>,
681    U: crate::expression::AppearsOnTable<QS>,
682{
683}
684
685impl<T, U> crate::expression::Expression for Like<T, U>
686where
687    T: crate::expression::Expression,
688    U: crate::expression::Expression,
689    <T as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
690    <U as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
691    crate::sql_types::is_nullable::IsSqlTypeNullable<<T as crate::expression::Expression>::SqlType>:
692        crate::sql_types::OneIsNullable<
693            crate::sql_types::is_nullable::IsSqlTypeNullable<
694                <U as crate::expression::Expression>::SqlType,
695            >,
696        >,
697    crate::sql_types::is_nullable::IsOneNullable<
698        <T as crate::expression::Expression>::SqlType,
699        <U as crate::expression::Expression>::SqlType,
700    >: crate::sql_types::MaybeNullableType<crate::sql_types::Bool>,
701{
702    type SqlType = crate::sql_types::is_nullable::MaybeNullable<
703        crate::sql_types::is_nullable::IsOneNullable<
704            <T as crate::expression::Expression>::SqlType,
705            <U as crate::expression::Expression>::SqlType,
706        >,
707        crate::sql_types::Bool,
708    >;
709}
710
711impl<T, U, DB> crate::query_builder::QueryFragment<DB> for Like<T, U>
712where
713    T: crate::query_builder::QueryFragment<DB> + crate::Expression,
714    U: crate::query_builder::QueryFragment<DB>,
715    DB: crate::backend::Backend,
716    DB: LikeIsAllowedForType<T::SqlType>,
717{
718    fn walk_ast<'b>(
719        &'b self,
720        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
721    ) -> crate::result::QueryResult<()> {
722        (self.left.walk_ast(out.reborrow())?);
723        (out.push_sql(" LIKE "));
724        (self.right.walk_ast(out.reborrow())?);
725        Ok(())
726    }
727}
728
729impl<S, T, U> crate::internal::operators_macro::FieldAliasMapper<S> for Like<T, U>
730where
731    S: crate::query_source::AliasSource,
732    T: crate::internal::operators_macro::FieldAliasMapper<S>,
733    U: crate::internal::operators_macro::FieldAliasMapper<S>,
734{
735    type Out = Like<
736        <T as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
737        <U as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
738    >;
739    fn map(self, alias: &crate::query_source::Alias<S>) -> Self::Out {
740        Like {
741            left: self.left.map(alias),
742            right: self.right.map(alias),
743        }
744    }
745}
746
747#[diagnostic::on_unimplemented(
748    message = "Cannot use the `LIKE` operator with expressions of the type `{ST}` for the backend `{Self}`",
749    note = "Expressions of the type `diesel::sql_types::Text` and `diesel::sql_types::Nullable<Text>` are \n\
750            allowed for all backends"
751)]
752#[cfg_attr(
753    feature = "postgres_backend",
754    diagnostic::on_unimplemented(
755        note = "Expressions of the type `diesel::sql_types::Binary` and `diesel::sql_types::Nullable<Binary>` are \n\
756            allowed for the PostgreSQL backend"
757    )
758)]
759pub trait LikeIsAllowedForType<ST>: Backend {}
760
761impl<DB> LikeIsAllowedForType<crate::sql_types::Text> for DB where DB: Backend {}
762
763impl<T, DB> LikeIsAllowedForType<crate::sql_types::Nullable<T>> for DB where
764    DB: Backend + LikeIsAllowedForType<T>
765{
766}