Skip to content

Commit 191fcf7

Browse files
authored
Merge pull request diesel-rs#1666 from diesel-rs/sg-parse-way-too-much-shit
Allow bounds on type parameters in `sql_function!`
2 parents a3896ce + 5ce87d7 commit 191fcf7

5 files changed

Lines changed: 502 additions & 98 deletions

File tree

Lines changed: 35 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,39 @@
1-
use backend::Backend;
2-
use expression::Expression;
3-
use query_builder::*;
4-
use result::QueryResult;
51
use sql_types::{IntoNullable, SqlOrd};
62

7-
macro_rules! ord_function {
8-
($fn_name:ident, $type_name:ident, $operator:expr, $docs:expr) => {
9-
#[doc=$docs]
10-
pub fn $fn_name<ST, T>(t: T) -> $type_name<T> where
11-
ST: SqlOrd,
12-
T: Expression<SqlType=ST>,
13-
{
14-
$type_name {
15-
target: t,
16-
}
17-
}
18-
19-
#[derive(Debug, Clone, Copy, QueryId)]
20-
#[doc(hidden)]
21-
pub struct $type_name<T> {
22-
target: T,
23-
}
24-
25-
impl<T: Expression> Expression for $type_name<T> where
26-
T::SqlType: IntoNullable,
27-
{
28-
type SqlType = <T::SqlType as IntoNullable>::Nullable;
29-
}
30-
31-
impl<T, DB> QueryFragment<DB> for $type_name<T> where
32-
T: Expression + QueryFragment<DB>,
33-
DB: Backend,
34-
{
35-
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
36-
out.push_sql(concat!($operator, "("));
37-
self.target.walk_ast(out.reborrow())?;
38-
out.push_sql(")");
39-
Ok(())
40-
}
41-
}
42-
43-
impl_selectable_expression!($type_name<T>);
44-
}
3+
sql_function! {
4+
/// Represents a SQL `MAX` function. This function can only take types which are
5+
/// ordered.
6+
///
7+
/// # Examples
8+
///
9+
/// ```rust
10+
/// # #[macro_use] extern crate diesel;
11+
/// # include!("../../doctest_setup.rs");
12+
/// # use diesel::dsl::*;
13+
/// #
14+
/// # fn main() {
15+
/// # use schema::animals::dsl::*;
16+
/// # let connection = establish_connection();
17+
/// assert_eq!(Ok(Some(8)), animals.select(max(legs)).first(&connection));
18+
/// # }
19+
fn max<ST: SqlOrd + IntoNullable>(expr: ST) -> ST::Nullable;
4520
}
4621

47-
ord_function!(
48-
max,
49-
Max,
50-
"MAX",
51-
"Represents a SQL `MAX` function. This function can only take types which are
52-
ordered.
53-
54-
# Examples
55-
56-
```rust
57-
# #[macro_use] extern crate diesel;
58-
# include!(\"../../doctest_setup.rs\");
59-
# use diesel::dsl::*;
60-
#
61-
# fn main() {
62-
# use schema::animals::dsl::*;
63-
# let connection = establish_connection();
64-
assert_eq!(Ok(Some(8)), animals.select(max(legs)).first(&connection));
65-
# }
66-
"
67-
);
68-
69-
ord_function!(
70-
min,
71-
Min,
72-
"MIN",
73-
"Represents a SQL `MIN` function. This function can only take types which are
74-
ordered.
75-
76-
# Examples
77-
78-
```rust
79-
# #[macro_use] extern crate diesel;
80-
# include!(\"../../doctest_setup.rs\");
81-
# use diesel::dsl::*;
82-
#
83-
# fn main() {
84-
# use schema::animals::dsl::*;
85-
# let connection = establish_connection();
86-
assert_eq!(Ok(Some(4)), animals.select(min(legs)).first(&connection));
87-
# }
88-
"
89-
);
22+
sql_function! {
23+
/// Represents a SQL `MIN` function. This function can only take types which are
24+
/// ordered.
25+
///
26+
/// # Examples
27+
///
28+
/// ```rust
29+
/// # #[macro_use] extern crate diesel;
30+
/// # include!("../../doctest_setup.rs");
31+
/// # use diesel::dsl::*;
32+
/// #
33+
/// # fn main() {
34+
/// # use schema::animals::dsl::*;
35+
/// # let connection = establish_connection();
36+
/// assert_eq!(Ok(Some(4)), animals.select(min(legs)).first(&connection));
37+
/// # }
38+
fn min<ST: SqlOrd + IntoNullable>(expr: ST) -> ST::Nullable;
39+
}

diesel/src/expression/functions/helper_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ pub type not<Expr> = operators::Not<Grouped<AsExprOf<Expr, Bool>>>;
1414
pub type Not<Expr> = not<Expr>;
1515

1616
/// The return type of [`max(expr)`](../dsl/fn.max.html)
17-
pub type max<Expr> = super::aggregate_ordering::Max<Expr>;
17+
pub type max<Expr> = super::aggregate_ordering::max::HelperType<SqlTypeOf<Expr>, Expr>;
1818

1919
/// The return type of [`min(expr)`](../dsl/fn.min.html)
20-
pub type min<Expr> = super::aggregate_ordering::Min<Expr>;
20+
pub type min<Expr> = super::aggregate_ordering::min::HelperType<SqlTypeOf<Expr>, Expr>;
2121

2222
/// The return type of [`sum(expr)`](../dsl/fn.sum.html)
2323
pub type sum<Expr> = super::aggregate_folding::sum::HelperType<SqlTypeOf<Expr>, Expr>;

diesel/src/expression/functions/mod.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,28 @@ macro_rules! sql_function_body {
9191
#[macro_export]
9292
#[doc(hidden)]
9393
macro_rules! __diesel_sql_function_body {
94+
// Entry point with type arguments. Pull out the rest of the body.
95+
(
96+
data = (
97+
meta = $meta:tt,
98+
fn_name = $fn_name:tt,
99+
),
100+
type_args = $type_args:tt,
101+
type_args_with_bounds = $type_args_with_bounds:tt,
102+
unparsed_tokens = (
103+
$args:tt -> $return_type:ty $(;)*
104+
),
105+
) => {
106+
__diesel_sql_function_body! {
107+
meta = $meta,
108+
fn_name = $fn_name,
109+
type_args = $type_args,
110+
type_args_with_bounds = $type_args_with_bounds,
111+
args = $args,
112+
return_type = $return_type,
113+
}
114+
};
115+
94116
// Entry point. We need to search the meta items for our special attributes
95117
(
96118
meta = $meta:tt,
@@ -372,16 +394,16 @@ macro_rules! sql_function {
372394
(
373395
$(#$meta:tt)*
374396
fn $fn_name:ident
375-
<$($type_arg:ident $(: $bound:path)*),* $(,)*>
376-
$args:tt -> $return_type:ty $(;)*
397+
<
398+
$($tokens:tt)*
377399
) => {
378-
__diesel_sql_function_body!(
379-
meta = ($(#$meta)*),
380-
fn_name = $fn_name,
381-
type_args = ($($type_arg,)*),
382-
type_args_with_bounds = ($($type_arg $(: $bound)*,)*),
383-
args = $args,
384-
return_type = $return_type,
400+
__diesel_parse_type_args!(
401+
data = (
402+
meta = ($(#$meta)*),
403+
fn_name = $fn_name,
404+
),
405+
callback = __diesel_sql_function_body,
406+
tokens = ($($tokens)*),
385407
);
386408
};
387409

0 commit comments

Comments
 (0)