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 (
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 (
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 (
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 (
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 (
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 (
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 (
306 type_args = ($($type_args:tt)+),
307 $($rest:tt)*
308 ) => {
309 };
310
311 (
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 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 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]
386macro_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]
649macro_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;