|
1 | | -#[macro_export] |
2 | | -#[doc(hidden)] |
3 | | -macro_rules! __diesel_sql_function_body { |
4 | | - // Entry point with type arguments. Pull out the rest of the body. |
5 | | - ( |
6 | | - data = ( |
7 | | - meta = $meta:tt, |
8 | | - fn_name = $fn_name:tt, |
9 | | - ), |
10 | | - type_args = $type_args:tt, |
11 | | - type_args_with_bounds = $type_args_with_bounds:tt, |
12 | | - unparsed_tokens = ( |
13 | | - $args:tt -> $return_type:ty $(;)* |
14 | | - ), |
15 | | - ) => { |
16 | | - __diesel_sql_function_body! { |
17 | | - meta = $meta, |
18 | | - fn_name = $fn_name, |
19 | | - type_args = $type_args, |
20 | | - type_args_with_bounds = $type_args_with_bounds, |
21 | | - args = $args, |
22 | | - return_type = $return_type, |
23 | | - } |
24 | | - }; |
25 | | - |
26 | | - // Entry point. We need to search the meta items for our special attributes |
27 | | - ( |
28 | | - meta = $meta:tt, |
29 | | - fn_name = $fn_name:ident, |
30 | | - $($rest:tt)* |
31 | | - ) => { |
32 | | - __diesel_sql_function_body! { |
33 | | - aggregate = no, |
34 | | - sql_name = stringify!($fn_name), |
35 | | - unchecked_meta = $meta, |
36 | | - meta = (), |
37 | | - fn_name = $fn_name, |
38 | | - $($rest)* |
39 | | - } |
40 | | - }; |
41 | | - |
42 | | - // Found #[aggregate] |
43 | | - ( |
44 | | - aggregate = $aggregate:tt, |
45 | | - sql_name = $sql_name:expr, |
46 | | - unchecked_meta = (#[aggregate] $($unchecked:tt)*), |
47 | | - meta = $meta:tt, |
48 | | - $($rest:tt)* |
49 | | - ) => { |
50 | | - __diesel_sql_function_body! { |
51 | | - aggregate = yes, |
52 | | - sql_name = $sql_name, |
53 | | - unchecked_meta = ($($unchecked)*), |
54 | | - meta = $meta, |
55 | | - $($rest)* |
56 | | - } |
57 | | - }; |
58 | | - |
59 | | - // Found #[sql_name]. |
60 | | - ( |
61 | | - aggregate = $aggregate:tt, |
62 | | - sql_name = $ignored:expr, |
63 | | - unchecked_meta = (#[sql_name = $sql_name:expr] $($unchecked:tt)*), |
64 | | - meta = $meta:tt, |
65 | | - $($rest:tt)* |
66 | | - ) => { |
67 | | - __diesel_sql_function_body! { |
68 | | - aggregate = $aggregate, |
69 | | - sql_name = $sql_name, |
70 | | - unchecked_meta = ($($unchecked)*), |
71 | | - meta = $meta, |
72 | | - $($rest)* |
73 | | - } |
74 | | - }; |
75 | | - |
76 | | - // Didn't find a special attribute |
77 | | - ( |
78 | | - aggregate = $aggregate:tt, |
79 | | - sql_name = $sql_name:expr, |
80 | | - unchecked_meta = (#$checked:tt $($unchecked:tt)*), |
81 | | - meta = ($($meta:tt)*), |
82 | | - $($rest:tt)* |
83 | | - ) => { |
84 | | - __diesel_sql_function_body! { |
85 | | - aggregate = $aggregate, |
86 | | - sql_name = $sql_name, |
87 | | - unchecked_meta = ($($unchecked)*), |
88 | | - meta = ($($meta)* #$checked), |
89 | | - $($rest)* |
90 | | - } |
91 | | - }; |
92 | | - |
93 | | - // Done searching for special attributes |
94 | | - ( |
95 | | - aggregate = $aggregate:tt, |
96 | | - sql_name = $sql_name:expr, |
97 | | - unchecked_meta = (), |
98 | | - meta = ($($meta:tt)*), |
99 | | - fn_name = $fn_name:ident, |
100 | | - type_args = ($($type_args:ident,)*), |
101 | | - type_args_with_bounds = ($($type_args_bounds:tt)*), |
102 | | - args = ($($arg_name:ident: $arg_type:ty),*), |
103 | | - return_type = $return_type:ty, |
104 | | - ) => { |
105 | | - $($meta)* |
106 | | - #[allow(non_camel_case_types)] |
107 | | - pub fn $fn_name<$($type_args_bounds)* $($arg_name),*>($($arg_name: $arg_name),*) |
108 | | - -> $fn_name::HelperType<$($type_args,)* $($arg_name),*> |
109 | | - where |
110 | | - $($arg_name: $crate::expression::AsExpression<$arg_type>),+ |
111 | | - { |
112 | | - $fn_name::$fn_name { |
113 | | - $($arg_name: $arg_name.as_expression(),)+ |
114 | | - $($type_args: ::std::marker::PhantomData,)* |
115 | | - } |
116 | | - } |
117 | | - |
118 | | - #[doc(hidden)] |
119 | | - #[allow(non_camel_case_types, non_snake_case, unused_imports)] |
120 | | - pub(crate) mod $fn_name { |
121 | | - use super::*; |
122 | | - use $crate::sql_types::*; |
123 | | - |
124 | | - #[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)] |
125 | | - pub struct $fn_name<$($type_args,)* $($arg_name),*> { |
126 | | - $(pub(in super) $arg_name: $arg_name,)* |
127 | | - $(pub(in super) $type_args: ::std::marker::PhantomData<$type_args>,)* |
128 | | - } |
129 | | - |
130 | | - pub type HelperType<$($type_args,)* $($arg_name),*> = $fn_name< |
131 | | - $($type_args,)* |
132 | | - $( |
133 | | - <$arg_name as $crate::expression::AsExpression<$arg_type>>::Expression |
134 | | - ),* |
135 | | - >; |
136 | | - |
137 | | - impl<$($type_args_bounds)* $($arg_name),*> |
138 | | - $crate::expression::Expression |
139 | | - for $fn_name<$($type_args,)* $($arg_name),*> |
140 | | - where |
141 | | - ($($arg_name),*): $crate::expression::Expression, |
142 | | - { |
143 | | - type SqlType = $return_type; |
144 | | - } |
145 | | - |
146 | | - impl<$($type_args_bounds)* $($arg_name),*, DB> |
147 | | - $crate::query_builder::QueryFragment<DB> |
148 | | - for $fn_name<$($type_args,)* $($arg_name),*> |
149 | | - where |
150 | | - DB: $crate::backend::Backend, |
151 | | - for<'a> ($(&'a $arg_name),*): $crate::query_builder::QueryFragment<DB>, |
152 | | - { |
153 | | - fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> { |
154 | | - out.push_sql(concat!($sql_name, "(")); |
155 | | - $crate::query_builder::QueryFragment::walk_ast( |
156 | | - &($(&self.$arg_name),*), out.reborrow())?; |
157 | | - out.push_sql(")"); |
158 | | - Ok(()) |
159 | | - } |
160 | | - } |
161 | | - |
162 | | - impl<$($type_args_bounds)* $($arg_name),*, QS> |
163 | | - $crate::expression::SelectableExpression<QS> |
164 | | - for $fn_name<$($type_args,)* $($arg_name),*> |
165 | | - where |
166 | | - $($arg_name: $crate::expression::SelectableExpression<QS>,)* |
167 | | - Self: $crate::expression::AppearsOnTable<QS>, |
168 | | - { |
169 | | - } |
170 | | - |
171 | | - impl<$($type_args_bounds)* $($arg_name),*, QS> |
172 | | - $crate::expression::AppearsOnTable<QS> |
173 | | - for $fn_name<$($type_args,)* $($arg_name),*> |
174 | | - where |
175 | | - $($arg_name: $crate::expression::AppearsOnTable<QS>,)* |
176 | | - Self: $crate::expression::Expression, |
177 | | - { |
178 | | - } |
179 | | - |
180 | | - static_cond! { |
181 | | - if $aggregate == no { |
182 | | - impl<$($type_args_bounds)* $($arg_name),*> |
183 | | - $crate::expression::NonAggregate |
184 | | - for $fn_name<$($type_args,)* $($arg_name),*> |
185 | | - where |
186 | | - $($arg_name: $crate::expression::NonAggregate,)* |
187 | | - Self: $crate::expression::Expression, |
188 | | - { |
189 | | - } |
190 | | - } |
191 | | - } |
192 | | - |
193 | | - __diesel_sqlite_register_fn! { |
194 | | - type_args = ($($type_args)*), |
195 | | - aggregate = $aggregate, |
196 | | - fn_name = $fn_name, |
197 | | - args = ($($arg_name,)+), |
198 | | - sql_args = ($($arg_type,)+), |
199 | | - ret = $return_type, |
200 | | - } |
201 | | - } |
202 | | - } |
203 | | -} |
204 | | - |
205 | | -#[macro_export] |
206 | | -#[doc(hidden)] |
207 | | -#[cfg(feature = "sqlite")] |
208 | | -macro_rules! __diesel_sqlite_register_fn { |
209 | | - // We can't handle generic functions for SQLite |
210 | | - ( |
211 | | - type_args = ($($type_args:tt)+), |
212 | | - $($rest:tt)* |
213 | | - ) => { |
214 | | - }; |
215 | | - |
216 | | - // We don't currently support aggregate functions for SQLite |
217 | | - ( |
218 | | - type_args = $ignored:tt, |
219 | | - aggregate = yes, |
220 | | - $($rest:tt)* |
221 | | - ) => { |
222 | | - }; |
223 | | - |
224 | | - ( |
225 | | - type_args = (), |
226 | | - aggregate = no, |
227 | | - fn_name = $fn_name:ident, |
228 | | - args = ($($args:ident,)+), |
229 | | - sql_args = $sql_args:ty, |
230 | | - ret = $ret:ty, |
231 | | - ) => { |
232 | | - #[allow(dead_code)] |
233 | | - /// Registers an implementation for this function on the given connection |
234 | | - /// |
235 | | - /// This function must be called for every `SqliteConnection` before |
236 | | - /// this SQL function can be used on SQLite. The implementation must be |
237 | | - /// deterministic (returns the same result given the same arguments). If |
238 | | - /// the function is nondeterministic, call |
239 | | - /// `register_nondeterministic_impl` instead. |
240 | | - pub fn register_impl<F, Ret, $($args,)+>( |
241 | | - conn: &$crate::SqliteConnection, |
242 | | - f: F, |
243 | | - ) -> $crate::QueryResult<()> |
244 | | - where |
245 | | - F: Fn($($args,)+) -> Ret + Send + 'static, |
246 | | - ($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>, |
247 | | - Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>, |
248 | | - { |
249 | | - conn.register_sql_function::<$sql_args, $ret, _, _, _>( |
250 | | - stringify!($fn_name), |
251 | | - true, |
252 | | - move |($($args,)+)| f($($args),+), |
253 | | - ) |
254 | | - } |
255 | | - |
256 | | - #[allow(dead_code)] |
257 | | - /// Registers an implementation for this function on the given connection |
258 | | - /// |
259 | | - /// This function must be called for every `SqliteConnection` before |
260 | | - /// this SQL function can be used on SQLite. |
261 | | - /// `register_nondeterministic_impl` should only be used if your |
262 | | - /// function can return different results with the same arguments (e.g. |
263 | | - /// `random`). If your function is deterministic, you should call |
264 | | - /// `register_impl` instead. |
265 | | - pub fn register_nondeterministic_impl<F, Ret, $($args,)+>( |
266 | | - conn: &$crate::SqliteConnection, |
267 | | - mut f: F, |
268 | | - ) -> $crate::QueryResult<()> |
269 | | - where |
270 | | - F: FnMut($($args,)+) -> Ret + Send + 'static, |
271 | | - ($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>, |
272 | | - Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>, |
273 | | - { |
274 | | - conn.register_sql_function::<$sql_args, $ret, _, _, _>( |
275 | | - stringify!($fn_name), |
276 | | - false, |
277 | | - move |($($args,)+)| f($($args),+), |
278 | | - ) |
279 | | - } |
280 | | - }; |
281 | | -} |
282 | | - |
283 | | -#[macro_export] |
284 | | -#[doc(hidden)] |
285 | | -#[cfg(not(feature = "sqlite"))] |
286 | | -macro_rules! __diesel_sqlite_register_fn { |
287 | | - ($($token:tt)*) => {}; |
288 | | -} |
289 | | - |
290 | 1 | #[macro_export] |
291 | 2 | /// Declare a sql function for use in your code. |
292 | 3 | /// |
@@ -452,51 +163,9 @@ macro_rules! __diesel_sqlite_register_fn { |
452 | 163 | /// # } |
453 | 164 | /// ``` |
454 | 165 | macro_rules! sql_function { |
455 | | - ($(#$meta:tt)* fn $fn_name:ident $args:tt $(;)*) => { |
456 | | - sql_function!($(#$meta)* fn $fn_name $args -> ()); |
457 | | - }; |
458 | | - |
459 | | - ($(#$meta:tt)* fn $fn_name:ident $args:tt -> $return_type:ty $(;)*) => { |
460 | | - sql_function!($(#$meta)* fn $fn_name <> $args -> $return_type); |
461 | | - }; |
462 | | - |
463 | | - ( |
464 | | - $(#$meta:tt)* |
465 | | - fn $fn_name:ident |
466 | | - < |
467 | | - $($tokens:tt)* |
468 | | - ) => { |
469 | | - __diesel_parse_type_args!( |
470 | | - data = ( |
471 | | - meta = ($(#$meta)*), |
472 | | - fn_name = $fn_name, |
473 | | - ), |
474 | | - callback = __diesel_sql_function_body, |
475 | | - tokens = ($($tokens)*), |
476 | | - ); |
477 | | - }; |
478 | | - |
479 | | - ($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty) => { |
480 | | - sql_function!($fn_name, $struct_name, $args -> $return_type, ""); |
481 | | - }; |
482 | | - |
483 | | - ($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty, $docs:expr) => { |
484 | | - sql_function!($fn_name, $struct_name, $args -> $return_type, $docs, ""); |
485 | | - }; |
486 | | - |
487 | | - ($fn_name:ident, $struct_name:ident, ($($arg_name:ident: $arg_type:ty),*)) => { |
488 | | - sql_function!($fn_name, $struct_name, ($($arg_name: $arg_type),*) -> ()); |
489 | | - }; |
490 | | - |
491 | | - ( |
492 | | - $fn_name:ident, |
493 | | - $struct_name:ident, |
494 | | - $args:tt -> $return_type:ty, |
495 | | - $docs:expr, |
496 | | - $helper_ty_docs:expr |
497 | | - ) => { |
498 | | - sql_function_body!($fn_name, $struct_name, $args -> $return_type, $docs, $helper_ty_docs); |
499 | | - }; |
| 166 | + ($($args:tt)*) => { |
| 167 | + sql_function_proc! { $($args)* } |
| 168 | + } |
500 | 169 | } |
501 | 170 |
|
502 | 171 | #[macro_export] |
|
0 commit comments