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>
221/// where
222///     T: Expression<SqlType = ST>,
223///     U: AsExpression<ST>,
224///     ST: SqlType + TypedExpressionType,
225/// {
226///     MyEq::new(left, right.as_expression())
227/// }
228///
229/// let users_with_name = users.select(id).filter(my_eq(name, "Sean"));
230///
231/// assert_eq!(Ok(1), users_with_name.first(connection));
232/// # }
233/// ```
234#[macro_export]
235macro_rules! infix_operator {
236    ($name:ident, $operator:expr) => {
237        $crate::infix_operator!($name, $operator, $crate::sql_types::Bool);
238    };
239
240    ($name:ident, $operator:expr, backend: $backend:ty) => {
241        $crate::infix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
242    };
243
244    ($name:ident, $operator:expr, $($return_ty:tt)::*) => {
245        $crate::__diesel_infix_operator!(
246            name = $name,
247            operator = $operator,
248            return_ty = NullableBasedOnArgs ($($return_ty)::*),
249            backend_ty_params = (DB,),
250            backend_ty = DB,
251        );
252    };
253
254    ($name:ident, $operator:expr, $($return_ty:tt)::*, backend: $backend:ty) => {
255        $crate::__diesel_infix_operator!(
256            name = $name,
257            operator = $operator,
258            return_ty = NullableBasedOnArgs ($($return_ty)::*),
259            backend_ty_params = (),
260            backend_ty = $backend,
261        );
262    };
263
264}
265#[macro_export]
266#[doc(hidden)]
267macro_rules! __diesel_infix_operator {
268    ($name:ident, $operator:expr, ConstantNullability $($return_ty:tt)::*) => {
269        $crate::__diesel_infix_operator!(
270            name = $name,
271            operator = $operator,
272            return_ty = ($($return_ty)::*),
273            backend_ty_params = (DB,),
274            backend_ty = DB,
275        );
276    };
277    ($name:ident, $operator:expr, __diesel_internal_SameResultAsInput, backend: $backend:ty) => {
278        $crate::__diesel_infix_operator!(
279            name = $name,
280            operator = $operator,
281            return_ty = (<T as $crate::expression::Expression>::SqlType),
282            backend_ty_params = (),
283            backend_ty = $backend,
284        );
285    };
286    ($name:ident, $operator:expr, ConstantNullability $($return_ty:tt)::*, backend: $backend:ty) => {
287        $crate::__diesel_infix_operator!(
288            name = $name,
289            operator = $operator,
290            return_ty = ($($return_ty)::*),
291            backend_ty_params = (),
292            backend_ty = $backend,
293        );
294    };
295
296    (
297        name = $name:ident,
298        operator = $operator:expr,
299        return_ty = NullableBasedOnArgs ($($return_ty:tt)+),
300        backend_ty_params = $backend_ty_params:tt,
301        backend_ty = $backend_ty:ty,
302    ) => {
303        $crate::__diesel_infix_operator!(
304            name = $name,
305            operator = $operator,
306            return_ty = (
307                $crate::sql_types::is_nullable::MaybeNullable<
308                    $crate::sql_types::is_nullable::IsOneNullable<
309                        <T as $crate::expression::Expression>::SqlType,
310                        <U as $crate::expression::Expression>::SqlType
311                    >,
312                    $($return_ty)+
313                >
314            ),
315            expression_bounds = (
316                $crate::sql_types::is_nullable::IsSqlTypeNullable<
317                    <T as $crate::expression::Expression>::SqlType
318                >: $crate::sql_types::OneIsNullable<
319                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
320                        <U as $crate::expression::Expression>::SqlType
321                    >
322                >,
323                $crate::sql_types::is_nullable::IsOneNullable<
324                    <T as $crate::expression::Expression>::SqlType,
325                    <U as $crate::expression::Expression>::SqlType
326                >: $crate::sql_types::MaybeNullableType<$($return_ty)+>,
327            ),
328            backend_ty_params = $backend_ty_params,
329            backend_ty = $backend_ty,
330        );
331    };
332
333    (
334        name = $name:ident,
335        operator = $operator:expr,
336        return_ty = ($($return_ty:tt)+),
337        backend_ty_params = $backend_ty_params:tt,
338        backend_ty = $backend_ty:ty,
339    ) => {
340        $crate::__diesel_infix_operator!(
341            name = $name,
342            operator = $operator,
343            return_ty = ($($return_ty)+),
344            expression_bounds = (),
345            backend_ty_params = $backend_ty_params,
346            backend_ty = $backend_ty,
347        );
348    };
349
350    (
351        name = $name:ident,
352        operator = $operator:expr,
353        return_ty = ($($return_ty:tt)+),
354        expression_bounds = ($($expression_bounds:tt)*),
355        backend_ty_params = $backend_ty_params:tt,
356        backend_ty = $backend_ty:ty,
357    ) => {
358        $crate::__diesel_operator_body!(
359            notation = infix,
360            struct_name = $name,
361            operator = $operator,
362            return_ty = ($($return_ty)+),
363            ty_params = (T, U,),
364            field_names = (left, right,),
365            backend_ty_params = $backend_ty_params,
366            backend_ty = $backend_ty,
367            expression_ty_params = (),
368            expression_bounds = (
369                T: $crate::expression::Expression,
370                U: $crate::expression::Expression,
371                <T as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
372                <U as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
373                $($expression_bounds)*
374            ),
375        );
376    };
377}
378
379#[macro_export]
380#[deprecated(since = "2.0.0", note = "use `diesel::infix_operator!` instead")]
381#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
382#[doc(hidden)]
383macro_rules! diesel_infix_operator {
384    ($($args:tt)*) => {
385        $crate::infix_operator!($($args)*);
386    }
387}
388
389/// Useful for libraries adding support for new SQL types. Apps should never
390/// need to call this.
391///
392/// Similar to [`infix_operator!`], but the generated type will only take
393/// a single argument rather than two. The operator SQL will be placed after
394/// the single argument. See [`infix_operator!`] for example usage.
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#[macro_export]
523macro_rules! prefix_operator {
524    ($name:ident, $operator:expr) => {
525        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool);
526    };
527
528    ($name:ident, $operator:expr, backend: $backend:ty) => {
529        $crate::prefix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
530    };
531
532    ($name:ident, $operator:expr, $return_ty:ty) => {
533        $crate::__diesel_operator_body!(
534            notation = prefix,
535            struct_name = $name,
536            operator = $operator,
537            return_ty = (
538                $crate::sql_types::is_nullable::MaybeNullable<
539                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
540                        <Expr as $crate::expression::Expression>::SqlType
541                    >,
542                    $return_ty,
543                >
544            ),
545            ty_params = (Expr,),
546            field_names = (expr,),
547            backend_ty_params = (DB,),
548            backend_ty = DB,
549            expression_ty_params = (),
550            expression_bounds = (
551                Expr: $crate::expression::Expression,
552                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
553                $crate::sql_types::is_nullable::IsSqlTypeNullable<
554                    <Expr as $crate::expression::Expression>::SqlType
555                >: $crate::sql_types::MaybeNullableType<$return_ty>,
556            ),
557        );
558    };
559
560    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
561        $crate::__diesel_operator_body!(
562            notation = prefix,
563            struct_name = $name,
564            operator = $operator,
565            return_ty = (
566                $crate::sql_types::is_nullable::MaybeNullable<
567                    $crate::sql_types::is_nullable::IsSqlTypeNullable<
568                        <Expr as $crate::expression::Expression>::SqlType
569                    >,
570                    $return_ty,
571                >
572            ),
573            ty_params = (Expr,),
574            field_names = (expr,),
575            backend_ty_params = (),
576            backend_ty = $backend,
577            expression_ty_params = (),
578            expression_bounds = (
579                Expr: $crate::expression::Expression,
580                <Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
581                $crate::sql_types::is_nullable::IsSqlTypeNullable<
582                    <Expr as $crate::expression::Expression>::SqlType
583                >: $crate::sql_types::MaybeNullableType<$return_ty>,
584            ),
585        );
586    };
587}
588
589#[macro_export]
590#[deprecated(since = "2.0.0", note = "use `diesel::prefix_operator!` instead")]
591#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
592#[doc(hidden)]
593macro_rules! diesel_prefix_operator {
594    ($($args:tt)*) => {
595        $crate::prefix_operator!($($args)*);
596    }
597}
598
599infix_operator!(And, " AND ");
600infix_operator!(Or, " OR ");
601infix_operator!(Escape, " ESCAPE ");
602infix_operator!(Eq, " = ");
603infix_operator!(Gt, " > ");
604infix_operator!(GtEq, " >= ");
605infix_operator!(Lt, " < ");
606infix_operator!(LtEq, " <= ");
607infix_operator!(NotEq, " != ");
608infix_operator!(NotLike, " NOT LIKE ");
609infix_operator!(Between, " BETWEEN ");
610infix_operator!(NotBetween, " NOT BETWEEN ");
611
612postfix_operator!(IsNull, " IS NULL");
613postfix_operator!(IsNotNull, " IS NOT NULL");
614postfix_operator!(
615    Asc,
616    " ASC",
617    crate::expression::expression_types::NotSelectable
618);
619postfix_operator!(
620    Desc,
621    " DESC",
622    crate::expression::expression_types::NotSelectable
623);
624
625prefix_operator!(Not, " NOT ");
626
627use crate::backend::{sql_dialect, Backend, SqlDialect};
628use crate::expression::{TypedExpressionType, ValidGrouping};
629use crate::insertable::{ColumnInsertValue, Insertable};
630use crate::query_builder::{QueryFragment, QueryId, ValuesClause};
631use crate::query_source::Column;
632use crate::sql_types::{DieselNumericOps, SqlType};
633
634impl<T, U> Insertable<T::Table> for Eq<T, U>
635where
636    T: Column,
637{
638    type Values = ValuesClause<ColumnInsertValue<T, U>, T::Table>;
639
640    fn values(self) -> Self::Values {
641        ValuesClause::new(ColumnInsertValue::new(self.right))
642    }
643}
644
645impl<'a, T, Tab, U> Insertable<Tab> for &'a Eq<T, U>
646where
647    T: Copy,
648    Eq<T, &'a U>: Insertable<Tab>,
649{
650    type Values = <Eq<T, &'a U> as Insertable<Tab>>::Values;
651
652    fn values(self) -> Self::Values {
653        Eq::new(self.left, &self.right).values()
654    }
655}
656
657/// This type represents a string concat operator
658#[diesel_derives::__diesel_public_if(
659    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
660    public_fields(left, right)
661)]
662#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
663pub struct Concat<L, R> {
664    /// The left side expression of the operator
665    pub(crate) left: L,
666    /// The right side expression of the operator
667    pub(crate) right: R,
668}
669
670impl<L, R> Concat<L, R> {
671    pub(crate) fn new(left: L, right: R) -> Self {
672        Self { left, right }
673    }
674}
675
676impl<L, R, ST> crate::expression::Expression for Concat<L, R>
677where
678    L: crate::expression::Expression<SqlType = ST>,
679    R: crate::expression::Expression<SqlType = ST>,
680    ST: SqlType + TypedExpressionType,
681{
682    type SqlType = ST;
683}
684
685impl_selectable_expression!(Concat<L, R>);
686
687impl<L, R, DB> QueryFragment<DB> for Concat<L, R>
688where
689    DB: Backend,
690    Self: QueryFragment<DB, DB::ConcatClause>,
691{
692    fn walk_ast<'b>(
693        &'b self,
694        pass: crate::query_builder::AstPass<'_, 'b, DB>,
695    ) -> crate::result::QueryResult<()> {
696        <Self as QueryFragment<DB, DB::ConcatClause>>::walk_ast(self, pass)
697    }
698}
699
700impl<L, R, DB> QueryFragment<DB, sql_dialect::concat_clause::ConcatWithPipesClause> for Concat<L, R>
701where
702    L: QueryFragment<DB>,
703    R: QueryFragment<DB>,
704    DB: Backend + SqlDialect<ConcatClause = sql_dialect::concat_clause::ConcatWithPipesClause>,
705{
706    fn walk_ast<'b>(
707        &'b self,
708        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
709    ) -> crate::result::QueryResult<()> {
710        // Since popular MySQL scalability layer Vitess does not support pipes in query parsing
711        // CONCAT has been implemented separately for MySQL (see MysqlConcatClause)
712        out.push_sql("(");
713        self.left.walk_ast(out.reborrow())?;
714        out.push_sql(" || ");
715        self.right.walk_ast(out.reborrow())?;
716        out.push_sql(")");
717        Ok(())
718    }
719}
720
721// need an explicit impl here to control which types are allowed
722#[derive(
723    Debug,
724    Clone,
725    Copy,
726    crate::query_builder::QueryId,
727    crate::sql_types::DieselNumericOps,
728    crate::expression::ValidGrouping,
729)]
730#[doc(hidden)]
731pub struct Like<T, U> {
732    pub(crate) left: T,
733    pub(crate) right: U,
734}
735
736impl<T, U> Like<T, U> {
737    pub(crate) fn new(left: T, right: U) -> Self {
738        Like { left, right }
739    }
740}
741
742impl<T, U, QS> crate::expression::SelectableExpression<QS> for Like<T, U>
743where
744    Like<T, U>: crate::expression::AppearsOnTable<QS>,
745    T: crate::expression::SelectableExpression<QS>,
746    U: crate::expression::SelectableExpression<QS>,
747{
748}
749
750impl<T, U, QS> crate::expression::AppearsOnTable<QS> for Like<T, U>
751where
752    Like<T, U>: crate::expression::Expression,
753    T: crate::expression::AppearsOnTable<QS>,
754    U: crate::expression::AppearsOnTable<QS>,
755{
756}
757
758impl<T, U> crate::expression::Expression for Like<T, U>
759where
760    T: crate::expression::Expression,
761    U: crate::expression::Expression,
762    <T as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
763    <U as crate::expression::Expression>::SqlType: crate::sql_types::SqlType,
764    crate::sql_types::is_nullable::IsSqlTypeNullable<<T as crate::expression::Expression>::SqlType>:
765        crate::sql_types::OneIsNullable<
766            crate::sql_types::is_nullable::IsSqlTypeNullable<
767                <U as crate::expression::Expression>::SqlType,
768            >,
769        >,
770    crate::sql_types::is_nullable::IsOneNullable<
771        <T as crate::expression::Expression>::SqlType,
772        <U as crate::expression::Expression>::SqlType,
773    >: crate::sql_types::MaybeNullableType<crate::sql_types::Bool>,
774{
775    type SqlType = crate::sql_types::is_nullable::MaybeNullable<
776        crate::sql_types::is_nullable::IsOneNullable<
777            <T as crate::expression::Expression>::SqlType,
778            <U as crate::expression::Expression>::SqlType,
779        >,
780        crate::sql_types::Bool,
781    >;
782}
783
784impl<T, U, DB> crate::query_builder::QueryFragment<DB> for Like<T, U>
785where
786    T: crate::query_builder::QueryFragment<DB> + crate::Expression,
787    U: crate::query_builder::QueryFragment<DB>,
788    DB: crate::backend::Backend,
789    DB: LikeIsAllowedForType<T::SqlType>,
790{
791    fn walk_ast<'b>(
792        &'b self,
793        mut out: crate::query_builder::AstPass<'_, 'b, DB>,
794    ) -> crate::result::QueryResult<()> {
795        (self.left.walk_ast(out.reborrow())?);
796        (out.push_sql(" LIKE "));
797        (self.right.walk_ast(out.reborrow())?);
798        Ok(())
799    }
800}
801
802impl<S, T, U> crate::internal::operators_macro::FieldAliasMapper<S> for Like<T, U>
803where
804    S: crate::query_source::AliasSource,
805    T: crate::internal::operators_macro::FieldAliasMapper<S>,
806    U: crate::internal::operators_macro::FieldAliasMapper<S>,
807{
808    type Out = Like<
809        <T as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
810        <U as crate::internal::operators_macro::FieldAliasMapper<S>>::Out,
811    >;
812    fn map(self, alias: &crate::query_source::Alias<S>) -> Self::Out {
813        Like {
814            left: self.left.map(alias),
815            right: self.right.map(alias),
816        }
817    }
818}
819
820#[diagnostic::on_unimplemented(
821    message = "cannot use the `LIKE` operator with expressions of the type `{ST}` for the backend `{Self}`",
822    note = "expressions of the type `diesel::sql_types::Text` and `diesel::sql_types::Nullable<Text>` are \n\
823            allowed for all backends"
824)]
825#[cfg_attr(
826    feature = "postgres_backend",
827    diagnostic::on_unimplemented(
828        note = "expressions of the type `diesel::sql_types::Binary` and `diesel::sql_types::Nullable<Binary>` are \n\
829            allowed for the PostgreSQL backend"
830    )
831)]
832pub trait LikeIsAllowedForType<ST>: Backend {}
833
834impl<DB> LikeIsAllowedForType<crate::sql_types::Text> for DB where DB: Backend {}
835
836#[cfg(feature = "postgres_backend")]
837impl LikeIsAllowedForType<crate::pg::sql_types::Citext> for crate::pg::Pg {}
838
839impl<T, DB> LikeIsAllowedForType<crate::sql_types::Nullable<T>> for DB where
840    DB: Backend + LikeIsAllowedForType<T>
841{
842}