diesel/expression/functions/
mod.rs

1#[macro_export]
2#[doc(hidden)]
3#[cfg(feature = "with-deprecated")]
4#[deprecated(
5    since = "1.3.0",
6    note = "The syntax of `sql_function!` and its output have changed significantly. This form has been deprecated. See the documentation of `sql_function!` for details on the new syntax."
7)]
8macro_rules! sql_function_body {
9    (
10        $fn_name:ident,
11        $struct_name:ident,
12        ($($arg_name:ident: $arg_type:ty),*) -> $return_type:ty,
13        $docs:expr,
14        $helper_ty_docs:expr
15    ) => {
16        #[allow(non_camel_case_types)]
17        #[derive(Debug, Clone, Copy, QueryId)]
18        #[doc(hidden)]
19        pub struct $struct_name<$($arg_name),*> {
20            $($arg_name: $arg_name),*
21        }
22
23        #[allow(non_camel_case_types)]
24        #[doc=$helper_ty_docs]
25        pub type $fn_name<$($arg_name),*> = $struct_name<$(
26            <$arg_name as $crate::expression::AsExpression<$arg_type>>::Expression
27        ),*>;
28
29        #[allow(non_camel_case_types)]
30        #[doc=$docs]
31        pub fn $fn_name<$($arg_name),*>($($arg_name: $arg_name),*)
32            -> $fn_name<$($arg_name),*>
33            where $($arg_name: $crate::expression::AsExpression<$arg_type>),+
34        {
35            $struct_name {
36                $($arg_name: $arg_name.as_expression()),+
37            }
38        }
39
40        #[allow(non_camel_case_types)]
41        impl<$($arg_name),*> $crate::expression::Expression for $struct_name<$($arg_name),*> where
42            for <'a> ($(&'a $arg_name),*): $crate::expression::Expression,
43        {
44            type SqlType = $return_type;
45        }
46
47        #[allow(non_camel_case_types)]
48        impl<$($arg_name),*, DB> $crate::query_builder::QueryFragment<DB> for $struct_name<$($arg_name),*> where
49            DB: $crate::backend::Backend,
50            for <'a> ($(&'a $arg_name),*): $crate::query_builder::QueryFragment<DB>,
51        {
52            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
53                out.push_sql(concat!(stringify!($fn_name), "("));
54                $crate::query_builder::QueryFragment::walk_ast(
55                    &($(&self.$arg_name),*), out.reborrow())?;
56                out.push_sql(")");
57                Ok(())
58            }
59        }
60
61        #[allow(non_camel_case_types)]
62        impl<$($arg_name),*, QS> $crate::expression::SelectableExpression<QS> for $struct_name<$($arg_name),*> where
63            $($arg_name: $crate::expression::SelectableExpression<QS>,)*
64            $struct_name<$($arg_name),*>: $crate::expression::AppearsOnTable<QS>,
65        {
66        }
67
68        #[allow(non_camel_case_types)]
69        impl<$($arg_name),*, QS> $crate::expression::AppearsOnTable<QS> for $struct_name<$($arg_name),*> where
70            $($arg_name: $crate::expression::AppearsOnTable<QS>,)*
71            $struct_name<$($arg_name),*>: $crate::expression::Expression,
72        {
73        }
74
75        #[allow(non_camel_case_types)]
76        impl<$($arg_name),*> $crate::expression::NonAggregate for $struct_name<$($arg_name),*> where
77            $($arg_name: $crate::expression::NonAggregate,)*
78            $struct_name<$($arg_name),*>: $crate::expression::Expression,
79        {
80        }
81    }
82}
83
84#[macro_export]
85#[doc(hidden)]
86#[cfg(not(feature = "with-deprecated"))]
87macro_rules! sql_function_body {
88    ($($args:tt)*) => {
89        compile_error!(
90            "You are using a deprecated form of `sql_function!`. \
91             You must enable the `with-deprecated` feature on `diesel`."
92        );
93    };
94}
95
96#[macro_export]
97#[doc(hidden)]
98macro_rules! __diesel_sql_function_body {
99    // Entry point with type arguments. Pull out the rest of the body.
100    (
101        data = (
102            meta = $meta:tt,
103            fn_name = $fn_name:tt,
104        ),
105        type_args = $type_args:tt,
106        type_args_with_bounds = $type_args_with_bounds:tt,
107        unparsed_tokens = (
108            $args:tt -> $return_type:ty $(;)*
109        ),
110    ) => {
111        __diesel_sql_function_body! {
112            meta = $meta,
113            fn_name = $fn_name,
114            type_args = $type_args,
115            type_args_with_bounds = $type_args_with_bounds,
116            args = $args,
117            return_type = $return_type,
118        }
119    };
120
121    // Entry point. We need to search the meta items for our special attributes
122    (
123        meta = $meta:tt,
124        fn_name = $fn_name:ident,
125        $($rest:tt)*
126    ) => {
127        __diesel_sql_function_body! {
128            aggregate = no,
129            sql_name = stringify!($fn_name),
130            unchecked_meta = $meta,
131            meta = (),
132            fn_name = $fn_name,
133            $($rest)*
134        }
135    };
136
137    // Found #[aggregate]
138    (
139        aggregate = $aggregate:tt,
140        sql_name = $sql_name:expr,
141        unchecked_meta = (#[aggregate] $($unchecked:tt)*),
142        meta = $meta:tt,
143        $($rest:tt)*
144    ) => {
145        __diesel_sql_function_body! {
146            aggregate = yes,
147            sql_name = $sql_name,
148            unchecked_meta = ($($unchecked)*),
149            meta = $meta,
150            $($rest)*
151        }
152    };
153
154    // Found #[sql_name].
155    (
156        aggregate = $aggregate:tt,
157        sql_name = $ignored:expr,
158        unchecked_meta = (#[sql_name = $sql_name:expr] $($unchecked:tt)*),
159        meta = $meta:tt,
160        $($rest:tt)*
161    ) => {
162        __diesel_sql_function_body! {
163            aggregate = $aggregate,
164            sql_name = $sql_name,
165            unchecked_meta = ($($unchecked)*),
166            meta = $meta,
167            $($rest)*
168        }
169    };
170
171    // Didn't find a special attribute
172    (
173        aggregate = $aggregate:tt,
174        sql_name = $sql_name:expr,
175        unchecked_meta = (#$checked:tt $($unchecked:tt)*),
176        meta = ($($meta:tt)*),
177        $($rest:tt)*
178    ) => {
179        __diesel_sql_function_body! {
180            aggregate = $aggregate,
181            sql_name = $sql_name,
182            unchecked_meta = ($($unchecked)*),
183            meta = ($($meta)* #$checked),
184            $($rest)*
185        }
186    };
187
188    // Done searching for special attributes
189    (
190        aggregate = $aggregate:tt,
191        sql_name = $sql_name:expr,
192        unchecked_meta = (),
193        meta = ($($meta:tt)*),
194        fn_name = $fn_name:ident,
195        type_args = ($($type_args:ident,)*),
196        type_args_with_bounds = ($($type_args_bounds:tt)*),
197        args = ($($arg_name:ident: $arg_type:ty),*),
198        return_type = $return_type:ty,
199    ) => {
200        $($meta)*
201        #[allow(non_camel_case_types)]
202        pub fn $fn_name<$($type_args_bounds)* $($arg_name),*>($($arg_name: $arg_name),*)
203            -> $fn_name::HelperType<$($type_args,)* $($arg_name),*>
204        where
205            $($arg_name: $crate::expression::AsExpression<$arg_type>),+
206        {
207            $fn_name::$fn_name {
208                $($arg_name: $arg_name.as_expression(),)+
209                $($type_args: ::std::marker::PhantomData,)*
210            }
211        }
212
213        #[doc(hidden)]
214        #[allow(non_camel_case_types, non_snake_case, unused_imports)]
215        pub(crate) mod $fn_name {
216            use super::*;
217            use $crate::sql_types::*;
218
219            #[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
220            pub struct $fn_name<$($type_args,)* $($arg_name),*> {
221                $(pub(in super) $arg_name: $arg_name,)*
222                $(pub(in super) $type_args: ::std::marker::PhantomData<$type_args>,)*
223            }
224
225            pub type HelperType<$($type_args,)* $($arg_name),*> = $fn_name<
226                $($type_args,)*
227                $(
228                    <$arg_name as $crate::expression::AsExpression<$arg_type>>::Expression
229                ),*
230            >;
231
232            impl<$($type_args_bounds)* $($arg_name),*>
233                $crate::expression::Expression
234                for $fn_name<$($type_args,)* $($arg_name),*>
235            where
236                ($($arg_name),*): $crate::expression::Expression,
237            {
238                type SqlType = $return_type;
239            }
240
241            impl<$($type_args_bounds)* $($arg_name),*, DB>
242                $crate::query_builder::QueryFragment<DB>
243                for $fn_name<$($type_args,)* $($arg_name),*>
244            where
245                DB: $crate::backend::Backend,
246                for<'a> ($(&'a $arg_name),*): $crate::query_builder::QueryFragment<DB>,
247            {
248                fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
249                    out.push_sql(concat!($sql_name, "("));
250                    $crate::query_builder::QueryFragment::walk_ast(
251                        &($(&self.$arg_name),*), out.reborrow())?;
252                    out.push_sql(")");
253                    Ok(())
254                }
255            }
256
257            impl<$($type_args_bounds)* $($arg_name),*, QS>
258                $crate::expression::SelectableExpression<QS>
259                for $fn_name<$($type_args,)* $($arg_name),*>
260            where
261                $($arg_name: $crate::expression::SelectableExpression<QS>,)*
262                Self: $crate::expression::AppearsOnTable<QS>,
263            {
264            }
265
266            impl<$($type_args_bounds)* $($arg_name),*, QS>
267                $crate::expression::AppearsOnTable<QS>
268                for $fn_name<$($type_args,)* $($arg_name),*>
269            where
270                $($arg_name: $crate::expression::AppearsOnTable<QS>,)*
271                Self: $crate::expression::Expression,
272            {
273            }
274
275            static_cond! {
276                if $aggregate == no {
277                    impl<$($type_args_bounds)* $($arg_name),*>
278                        $crate::expression::NonAggregate
279                        for $fn_name<$($type_args,)* $($arg_name),*>
280                    where
281                        $($arg_name: $crate::expression::NonAggregate,)*
282                        Self: $crate::expression::Expression,
283                    {
284                    }
285                }
286            }
287
288            __diesel_sqlite_register_fn! {
289                type_args = ($($type_args)*),
290                aggregate = $aggregate,
291                fn_name = $fn_name,
292                args = ($($arg_name,)+),
293                sql_args = ($($arg_type,)+),
294                ret = $return_type,
295            }
296        }
297    }
298}
299
300#[macro_export]
301#[doc(hidden)]
302#[cfg(feature = "sqlite")]
303macro_rules! __diesel_sqlite_register_fn {
304    // We can't handle generic functions for SQLite
305    (
306        type_args = ($($type_args:tt)+),
307        $($rest:tt)*
308    ) => {
309    };
310
311    // We don't currently support aggregate functions for SQLite
312    (
313        type_args = $ignored:tt,
314        aggregate = yes,
315        $($rest:tt)*
316    ) => {
317    };
318
319    (
320        type_args = (),
321        aggregate = no,
322        fn_name = $fn_name:ident,
323        args = ($($args:ident,)+),
324        sql_args = $sql_args:ty,
325        ret = $ret:ty,
326    ) => {
327        #[allow(dead_code)]
328        /// Registers an implementation for this function on the given connection
329        ///
330        /// This function must be called for every `SqliteConnection` before
331        /// this SQL function can be used on SQLite. The implementation must be
332        /// deterministic (returns the same result given the same arguments). If
333        /// the function is nondeterministic, call
334        /// `register_nondeterministic_impl` instead.
335        pub fn register_impl<F, Ret, $($args,)+>(
336            conn: &$crate::SqliteConnection,
337            f: F,
338        ) -> $crate::QueryResult<()>
339        where
340            F: Fn($($args,)+) -> Ret + Send + 'static,
341            ($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>,
342            Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>,
343        {
344            conn.register_sql_function::<$sql_args, $ret, _, _, _>(
345                stringify!($fn_name),
346                true,
347                move |($($args,)+)| f($($args),+),
348            )
349        }
350
351        #[allow(dead_code)]
352        /// Registers an implementation for this function on the given connection
353        ///
354        /// This function must be called for every `SqliteConnection` before
355        /// this SQL function can be used on SQLite.
356        /// `register_nondeterministic_impl` should only be used if your
357        /// function can return different results with the same arguments (e.g.
358        /// `random`). If your function is deterministic, you should call
359        /// `register_impl` instead.
360        pub fn register_nondeterministic_impl<F, Ret, $($args,)+>(
361            conn: &$crate::SqliteConnection,
362            mut f: F,
363        ) -> $crate::QueryResult<()>
364        where
365            F: FnMut($($args,)+) -> Ret + Send + 'static,
366            ($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>,
367            Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>,
368        {
369            conn.register_sql_function::<$sql_args, $ret, _, _, _>(
370                stringify!($fn_name),
371                false,
372                move |($($args,)+)| f($($args),+),
373            )
374        }
375    };
376}
377
378#[macro_export]
379#[doc(hidden)]
380#[cfg(not(feature = "sqlite"))]
381macro_rules! __diesel_sqlite_register_fn {
382    ($($token:tt)*) => {};
383}
384
385#[macro_export]
386/// Declare a sql function for use in your code.
387///
388/// Diesel only provides support for a very small number of SQL functions.
389/// This macro enables you to add additional functions from the SQL standard,
390/// as well as any custom functions your application might have.
391///
392/// The syntax for this macro is very similar to that of a normal Rust function,
393/// except the argument and return types will be the SQL types being used.
394/// Typically these types will come from [`diesel::sql_types`].
395///
396/// This macro will generate two items. A function with the name that you've
397/// given, and a module with a helper type representing the return type of your
398/// function. For example, this invocation:
399///
400/// ```ignore
401/// sql_function!(fn lower(x: Text) -> Text);
402/// ```
403///
404/// will generate this code:
405///
406/// ```ignore
407/// pub fn lower<X>(x: X) -> lower::HelperType<X> {
408///     ...
409/// }
410///
411/// pub(crate) mod lower {
412///     pub type HelperType<X> = ...;
413/// }
414/// ```
415///
416/// If you are using this macro for part of a library, where the function is
417/// part of your public API, it is highly recommended that you re-export this
418/// helper type with the same name as your function. This is the standard
419/// structure:
420///
421/// ```ignore
422/// pub mod functions {
423///     use super::types::*;
424///     use diesel::sql_types::*;
425///
426///     sql_function! {
427///         /// Represents the Pg `LENGTH` function used with `tsvector`s.
428///         fn length(x: TsVector) -> Integer;
429///     }
430/// }
431///
432/// pub mod helper_types {
433///     /// The return type of `length(expr)`
434///     pub type Length<Expr> = functions::length::HelperType<Expr>;
435/// }
436///
437/// pub mod dsl {
438///     pub use functions::*;
439///     pub use helper_types::*;
440/// }
441/// ```
442///
443/// Most attributes given to this macro will be put on the generated function
444/// (including doc comments).
445///
446/// # Adding Doc Comments
447///
448/// ```no_run
449/// # #[macro_use] extern crate diesel;
450/// # use diesel::*;
451/// #
452/// # table! { crates { id -> Integer, name -> VarChar, } }
453/// #
454/// use diesel::sql_types::Text;
455///
456/// sql_function! {
457///     /// Represents the `canon_crate_name` SQL function, created in
458///     /// migration ....
459///     fn canon_crate_name(a: Text) -> Text;
460/// }
461///
462/// # fn main() {
463/// # use self::crates::dsl::*;
464/// let target_name = "diesel";
465/// crates.filter(canon_crate_name(name).eq(canon_crate_name(target_name)));
466/// // This will generate the following SQL
467/// // SELECT * FROM crates WHERE canon_crate_name(crates.name) = canon_crate_name($1)
468/// # }
469/// ```
470///
471/// # Special Attributes
472///
473/// There are a handful of special attributes that Diesel will recognize. They
474/// are:
475///
476/// - `#[aggregate]`
477///   - Indicates that this is an aggregate function, and that `NonAggregate`
478///     should not be implemented.
479/// - `#[sql_name="name"]`
480///   - The SQL to be generated is different than the Rust name of the function.
481///     This can be used to represent functions which can take many argument
482///     types, or to capitalize function names.
483///
484/// Functions can also be generic. Take the definition of `sum` for an example
485/// of all of this:
486///
487/// ```no_run
488/// # #[macro_use] extern crate diesel;
489/// # use diesel::*;
490/// #
491/// # table! { crates { id -> Integer, name -> VarChar, } }
492/// #
493/// use diesel::sql_types::Foldable;
494///
495/// sql_function! {
496///     #[aggregate]
497///     #[sql_name = "SUM"]
498///     fn sum<ST: Foldable>(expr: ST) -> ST::Sum;
499/// }
500///
501/// # fn main() {
502/// # use self::crates::dsl::*;
503/// crates.select(sum(id));
504/// # }
505/// ```
506///
507/// # Use with SQLite
508///
509/// On most backends, the implementation of the function is defined in a
510/// migration using `CREATE FUNCTION`. On SQLite, the function is implemented in
511/// Rust instead. You must call `register_impl` or
512/// `register_nondeterministic_impl` with every connection before you can use
513/// the function.
514///
515/// These functions will only be generated if the `sqlite` feature is enabled,
516/// and the function is not generic. Generic functions and variadic functions
517/// are not supported on SQLite.
518///
519/// ```rust
520/// # #[macro_use] extern crate diesel;
521/// # use diesel::*;
522/// #
523/// # #[cfg(feature = "sqlite")]
524/// # fn main() {
525/// #     run_test().unwrap();
526/// # }
527/// #
528/// # #[cfg(not(feature = "sqlite"))]
529/// # fn main() {
530/// # }
531/// #
532/// use diesel::sql_types::{Integer, Double};
533/// sql_function!(fn add_mul(x: Integer, y: Integer, z: Double) -> Double);
534///
535/// # #[cfg(feature = "sqlite")]
536/// # fn run_test() -> Result<(), Box<::std::error::Error>> {
537/// let connection = SqliteConnection::establish(":memory:")?;
538///
539/// add_mul::register_impl(&connection, |x: i32, y: i32, z: f64| {
540///     (x + y) as f64 * z
541/// })?;
542///
543/// let result = select(add_mul(1, 2, 1.5))
544///     .get_result::<f64>(&connection)?;
545/// assert_eq!(4.5, result);
546/// #     Ok(())
547/// # }
548/// ```
549macro_rules! sql_function {
550    ($(#$meta:tt)* fn $fn_name:ident $args:tt $(;)*) => {
551        sql_function!($(#$meta)* fn $fn_name $args -> ());
552    };
553
554    ($(#$meta:tt)* fn $fn_name:ident $args:tt -> $return_type:ty $(;)*) => {
555        sql_function!($(#$meta)* fn $fn_name <> $args -> $return_type);
556    };
557
558    (
559        $(#$meta:tt)*
560        fn $fn_name:ident
561        <
562        $($tokens:tt)*
563    ) => {
564        __diesel_parse_type_args!(
565            data = (
566                meta = ($(#$meta)*),
567                fn_name = $fn_name,
568            ),
569            callback = __diesel_sql_function_body,
570            tokens = ($($tokens)*),
571        );
572    };
573
574    ($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty) => {
575        sql_function!($fn_name, $struct_name, $args -> $return_type, "");
576    };
577
578    ($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty, $docs:expr) => {
579        sql_function!($fn_name, $struct_name, $args -> $return_type, $docs, "");
580    };
581
582    ($fn_name:ident, $struct_name:ident, ($($arg_name:ident: $arg_type:ty),*)) => {
583        sql_function!($fn_name, $struct_name, ($($arg_name: $arg_type),*) -> ());
584    };
585
586    (
587        $fn_name:ident,
588        $struct_name:ident,
589        $args:tt -> $return_type:ty,
590        $docs:expr,
591        $helper_ty_docs:expr
592    ) => {
593        sql_function_body!($fn_name, $struct_name, $args -> $return_type, $docs, $helper_ty_docs);
594    };
595}
596
597#[macro_export]
598#[doc(hidden)]
599macro_rules! no_arg_sql_function_body_except_to_sql {
600    ($type_name:ident, $return_type:ty, $docs:expr) => {
601        #[allow(non_camel_case_types)]
602        #[doc=$docs]
603        #[derive(Debug, Clone, Copy, QueryId)]
604        pub struct $type_name;
605
606        impl $crate::expression::Expression for $type_name {
607            type SqlType = $return_type;
608        }
609
610        impl<QS> $crate::expression::SelectableExpression<QS> for $type_name {}
611
612        impl<QS> $crate::expression::AppearsOnTable<QS> for $type_name {}
613
614        impl $crate::expression::NonAggregate for $type_name {}
615    };
616}
617
618#[macro_export]
619#[doc(hidden)]
620macro_rules! no_arg_sql_function_body {
621    ($type_name:ident, $return_type:ty, $docs:expr, $($constraint:ident)::+) => {
622        no_arg_sql_function_body_except_to_sql!($type_name, $return_type, $docs);
623
624        impl<DB> $crate::query_builder::QueryFragment<DB> for $type_name where
625            DB: $crate::backend::Backend + $($constraint)::+,
626        {
627            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
628                out.push_sql(concat!(stringify!($type_name), "()"));
629                Ok(())
630            }
631        }
632    };
633
634    ($type_name:ident, $return_type:ty, $docs:expr) => {
635        no_arg_sql_function_body_except_to_sql!($type_name, $return_type, $docs);
636
637        impl<DB> $crate::query_builder::QueryFragment<DB> for $type_name where
638            DB: $crate::backend::Backend,
639        {
640            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
641                out.push_sql(concat!(stringify!($type_name), "()"));
642                Ok(())
643            }
644        }
645    };
646}
647
648#[macro_export]
649/// Declare a 0 argument SQL function for use in your code. This will generate a
650/// unit struct, which is an expression representing calling this function. See
651/// [`now`](expression/dsl/struct.now.html) for example output. `now` was
652/// generated using:
653///
654/// ```no_run
655/// # #[macro_use] extern crate diesel;
656/// # pub use diesel::*;
657/// no_arg_sql_function!(now, sql_types::Timestamp, "Represents the SQL NOW() function");
658/// # fn main() {}
659/// ```
660///
661/// You can optionally pass the name of a trait, as a constraint for backends which support the
662/// function.
663macro_rules! no_arg_sql_function {
664    ($type_name:ident, $return_type:ty) => {
665        no_arg_sql_function!($type_name, $return_type, "");
666    };
667
668    ($type_name:ident, $return_type:ty, $docs:expr) => {
669        no_arg_sql_function_body!($type_name, $return_type, $docs);
670    };
671
672    ($type_name:ident, $return_type:ty, $docs:expr, $($constraint:ident)::+) => {
673        no_arg_sql_function_body!($type_name, $return_type, $docs, $($constraint)::+);
674    };
675}
676
677pub mod aggregate_folding;
678pub mod aggregate_ordering;
679pub mod date_and_time;
680pub mod helper_types;