diesel/expression/
operators.rs

1#![cfg_attr(rustfmt, rustfmt_skip)] // https://github.com/rust-lang-nursery/rustfmt/issues/2755
2
3#[macro_export]
4#[doc(hidden)]
5macro_rules! __diesel_operator_body {
6    (
7        notation = $notation:ident,
8        struct_name = $name:ident,
9        operator = $operator:expr,
10        return_ty = ReturnBasedOnArgs,
11        ty_params = ($($ty_param:ident,)+),
12        field_names = $field_names:tt,
13        backend_ty_params = $backend_ty_params:tt,
14        backend_ty = $backend_ty:ty,
15    ) => {
16        __diesel_operator_body! {
17            notation = $notation,
18            struct_name = $name,
19            operator = $operator,
20            return_ty = ST,
21            ty_params = ($($ty_param,)+),
22            field_names = $field_names,
23            backend_ty_params = $backend_ty_params,
24            backend_ty = $backend_ty,
25            expression_ty_params = (ST,),
26            expression_bounds = ($($ty_param: $crate::expression::Expression<SqlType = ST>,)+),
27        }
28    };
29
30    (
31        notation = $notation:ident,
32        struct_name = $name:ident,
33        operator = $operator:expr,
34        return_ty = $return_ty:ty,
35        ty_params = ($($ty_param:ident,)+),
36        field_names = $field_names:tt,
37        backend_ty_params = $backend_ty_params:tt,
38        backend_ty = $backend_ty:ty,
39    ) => {
40        __diesel_operator_body! {
41            notation = $notation,
42            struct_name = $name,
43            operator = $operator,
44            return_ty = $return_ty,
45            ty_params = ($($ty_param,)+),
46            field_names = $field_names,
47            backend_ty_params = $backend_ty_params,
48            backend_ty = $backend_ty,
49            expression_ty_params = (),
50            expression_bounds = ($($ty_param: $crate::expression::Expression,)+),
51        }
52    };
53
54    (
55        notation = $notation:ident,
56        struct_name = $name:ident,
57        operator = $operator:expr,
58        return_ty = $return_ty:ty,
59        ty_params = ($($ty_param:ident,)+),
60        field_names = ($($field_name:ident,)+),
61        backend_ty_params = ($($backend_ty_param:ident,)*),
62        backend_ty = $backend_ty:ty,
63        expression_ty_params = ($($expression_ty_params:ident,)*),
64        expression_bounds = ($($expression_bounds:tt)*),
65    ) => {
66        #[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
67        #[doc(hidden)]
68        pub struct $name<$($ty_param,)+> {
69            $(pub(crate) $field_name: $ty_param,)+
70        }
71
72        impl<$($ty_param,)+> $name<$($ty_param,)+> {
73            pub fn new($($field_name: $ty_param,)+) -> Self {
74                $name { $($field_name,)+ }
75            }
76        }
77
78        impl_selectable_expression!($name<$($ty_param),+>);
79
80        impl<$($ty_param,)+ $($expression_ty_params,)*> $crate::expression::Expression for $name<$($ty_param,)+> where
81            $($expression_bounds)*
82        {
83            type SqlType = $return_ty;
84        }
85
86        impl<$($ty_param,)+> $crate::expression::NonAggregate for $name<$($ty_param,)+> where
87            $($ty_param: $crate::expression::NonAggregate,)+
88        {
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(&self, mut out: $crate::query_builder::AstPass<$backend_ty>) -> $crate::result::QueryResult<()> {
97                __diesel_operator_to_sql!(
98                    notation = $notation,
99                    operator_expr = out.push_sql($operator),
100                    field_exprs = ($(self.$field_name.walk_ast(out.reborrow())?),+),
101                );
102                Ok(())
103            }
104        }
105    }
106}
107
108#[macro_export]
109#[doc(hidden)]
110macro_rules! __diesel_operator_to_sql {
111    (
112        notation = infix,
113        operator_expr = $op:expr,
114        field_exprs = ($left:expr, $right:expr),
115    ) => {
116        $left;
117        $op;
118        $right;
119    };
120
121    (
122        notation = postfix,
123        operator_expr = $op:expr,
124        field_exprs = ($expr:expr),
125    ) => {
126        $expr;
127        $op;
128    };
129
130    (
131        notation = prefix,
132        operator_expr = $op:expr,
133        field_exprs = ($expr:expr),
134    ) => {
135        $op;
136        $expr;
137    };
138}
139
140/// Useful for libraries adding support for new SQL types. Apps should never
141/// need to call this.
142///
143/// This will create a new type with the given name. It will implement all
144/// methods needed to be used as an expression in Diesel, placing the given
145/// SQL between the two elements. The third argument specifies the SQL type
146/// that the operator returns. If it is not given, the type will be assumed
147/// to be `Bool`.
148///
149/// If the operator is specific to a single backend, you can specify this by
150/// adding `backend: Pg` or similar as the last argument.
151///
152/// It should be noted that the generated impls will not constrain the SQL
153/// types of the arguments. You should ensure that they are of the right
154/// type in your function which constructs the operator.
155///
156/// Typically you would not expose the type that this generates directly. You'd
157/// expose a function (or trait) used to construct the expression, and a helper
158/// type which represents the return type of that function. See the source of
159/// `diesel::expression::expression_methods` and
160/// `diesel::expression::helper_types` for real world examples of this.
161///
162/// # Examples
163///
164/// # Possible invocations
165///
166/// ```ignore
167/// // The SQL type will be boolean. The backend will not be constrained
168/// diesel_infix_operator!(Matches, " @@ ");
169///
170/// // Queries which try to execute `Contains` on a backend other than Pg
171/// // will fail to compile
172/// diesel_infix_operator!(Contains, " @> ", backend: Pg);
173///
174/// // The type of `Concat` will be `TsVector` rather than Bool
175/// diesel_infix_operator!(Concat, " || ", TsVector);
176///
177/// // It is perfectly fine to have multiple operators with the same SQL.
178/// // Diesel will ensure that the queries are always unambiguous in which
179/// // operator applies
180/// diesel_infix_operator!(Or, " || ", TsQuery);
181///
182/// // Specifying both the return types and the backend
183/// diesel_infix_operator!(And, " && ", TsQuery, backend: Pg);
184/// ```
185///
186/// ## Example usage
187///
188/// ```rust
189/// # #[macro_use] extern crate diesel;
190/// # include!("../doctest_setup.rs");
191/// #
192/// # fn main() {
193/// #     use schema::users::dsl::*;
194/// #     let connection = establish_connection();
195/// diesel_infix_operator!(MyEq, " = ");
196///
197/// use diesel::expression::AsExpression;
198///
199/// // Normally you would put this on a trait instead
200/// fn my_eq<T, U>(left: T, right: U) -> MyEq<T, U::Expression> where
201///     T: Expression,
202///     U: AsExpression<T::SqlType>,
203/// {
204///     MyEq::new(left, right.as_expression())
205/// }
206///
207/// let users_with_name = users.select(id).filter(my_eq(name, "Sean"));
208///
209/// assert_eq!(Ok(1), users_with_name.first(&connection));
210/// # }
211/// ```
212#[macro_export]
213macro_rules! diesel_infix_operator {
214    ($name:ident, $operator:expr) => {
215        diesel_infix_operator!($name, $operator, $crate::sql_types::Bool);
216    };
217
218    ($name:ident, $operator:expr, backend: $backend:ty) => {
219        diesel_infix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
220    };
221
222    ($name:ident, $operator:expr, $($return_ty:tt)::*) => {
223        __diesel_operator_body!(
224            notation = infix,
225            struct_name = $name,
226            operator = $operator,
227            return_ty = $($return_ty)::*,
228            ty_params = (T, U,),
229            field_names = (left, right,),
230            backend_ty_params = (DB,),
231            backend_ty = DB,
232        );
233    };
234
235    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
236        __diesel_operator_body!(
237            notation = infix,
238            struct_name = $name,
239            operator = $operator,
240            return_ty = $return_ty,
241            ty_params = (T, U,),
242            field_names = (left, right,),
243            backend_ty_params = (),
244            backend_ty = $backend,
245        );
246    };
247}
248
249/// Useful for libraries adding support for new SQL types. Apps should never
250/// need to call this.
251///
252/// Similar to [`diesel_infix_operator!`], but the generated type will only take
253/// a single argument rather than two. The operator SQL will be placed after
254/// the single argument. See [`diesel_infix_operator!`] for example usage.
255///
256/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
257#[macro_export]
258macro_rules! diesel_postfix_operator {
259    ($name:ident, $operator:expr) => {
260        diesel_postfix_operator!($name, $operator, $crate::sql_types::Bool);
261    };
262
263    ($name:ident, $operator:expr, backend: $backend:ty) => {
264        diesel_postfix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
265    };
266
267    ($name:ident, $operator:expr, $return_ty:ty) => {
268        __diesel_operator_body!(
269            notation = postfix,
270            struct_name = $name,
271            operator = $operator,
272            return_ty = $return_ty,
273            ty_params = (Expr,),
274            field_names = (expr,),
275            backend_ty_params = (DB,),
276            backend_ty = DB,
277        );
278    };
279
280    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
281        __diesel_operator_body!(
282            notation = postfix,
283            struct_name = $name,
284            operator = $operator,
285            return_ty = $return_ty,
286            ty_params = (Expr,),
287            field_names = (expr,),
288            backend_ty_params = (),
289            backend_ty = $backend,
290        );
291    };
292}
293
294/// Useful for libraries adding support for new SQL types. Apps should never
295/// need to call this.
296///
297/// Similar to [`diesel_infix_operator!`], but the generated type will only take
298/// a single argument rather than two. The operator SQL will be placed before
299/// the single argument. See [`diesel_infix_operator!`] for example usage.
300///
301/// [`diesel_infix_operator!`]: macro.diesel_infix_operator.html
302#[macro_export]
303macro_rules! diesel_prefix_operator {
304    ($name:ident, $operator:expr) => {
305        diesel_prefix_operator!($name, $operator, $crate::sql_types::Bool);
306    };
307
308    ($name:ident, $operator:expr, backend: $backend:ty) => {
309        diesel_prefix_operator!($name, $operator, $crate::sql_types::Bool, backend: $backend);
310    };
311
312    ($name:ident, $operator:expr, $return_ty:ty) => {
313        __diesel_operator_body!(
314            notation = prefix,
315            struct_name = $name,
316            operator = $operator,
317            return_ty = $return_ty,
318            ty_params = (Expr,),
319            field_names = (expr,),
320            backend_ty_params = (DB,),
321            backend_ty = DB,
322        );
323    };
324
325    ($name:ident, $operator:expr, $return_ty:ty, backend: $backend:ty) => {
326        __diesel_operator_body!(
327            notation = prefix,
328            struct_name = $name,
329            operator = $operator,
330            return_ty = $return_ty,
331            ty_params = (Expr,),
332            field_names = (expr,),
333            backend_ty_params = (),
334            backend_ty = $backend,
335        );
336    };
337}
338
339diesel_infix_operator!(Concat, " || ", ReturnBasedOnArgs);
340diesel_infix_operator!(And, " AND ");
341diesel_infix_operator!(Between, " BETWEEN ");
342diesel_infix_operator!(Escape, " ESCAPE ");
343diesel_infix_operator!(Eq, " = ");
344diesel_infix_operator!(Gt, " > ");
345diesel_infix_operator!(GtEq, " >= ");
346diesel_infix_operator!(Like, " LIKE ");
347diesel_infix_operator!(Lt, " < ");
348diesel_infix_operator!(LtEq, " <= ");
349diesel_infix_operator!(NotBetween, " NOT BETWEEN ");
350diesel_infix_operator!(NotEq, " != ");
351diesel_infix_operator!(NotLike, " NOT LIKE ");
352diesel_infix_operator!(Or, " OR ");
353
354diesel_postfix_operator!(IsNull, " IS NULL");
355diesel_postfix_operator!(IsNotNull, " IS NOT NULL");
356diesel_postfix_operator!(Asc, " ASC", ());
357diesel_postfix_operator!(Desc, " DESC", ());
358
359diesel_prefix_operator!(Not, "NOT ");
360
361use insertable::{ColumnInsertValue, Insertable};
362use query_builder::ValuesClause;
363use query_source::Column;
364
365impl<T, U> Insertable<T::Table> for Eq<T, U>
366where
367    T: Column,
368{
369    type Values = ValuesClause<ColumnInsertValue<T, U>, T::Table>;
370
371    fn values(self) -> Self::Values {
372        ValuesClause::new(ColumnInsertValue::Expression(self.left, self.right))
373    }
374}
375
376impl<'a, T, Tab, U> Insertable<Tab> for &'a Eq<T, U>
377where
378    T: Copy,
379    Eq<T, &'a U>: Insertable<Tab>,
380{
381    type Values = <Eq<T, &'a U> as Insertable<Tab>>::Values;
382
383    fn values(self) -> Self::Values {
384        Eq::new(self.left, &self.right).values()
385    }
386}