#[macro_export]
#[doc(hidden)]
#[cfg(feature = "with-deprecated")]
#[deprecated(
since = "1.3.0",
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."
)]
macro_rules! sql_function_body {
(
$fn_name:ident,
$struct_name:ident,
($($arg_name:ident: $arg_type:ty),*) -> $return_type:ty,
$docs:expr,
$helper_ty_docs:expr
) => {
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, QueryId)]
#[doc(hidden)]
pub struct $struct_name<$($arg_name),*> {
$($arg_name: $arg_name),*
}
#[allow(non_camel_case_types)]
#[doc=$helper_ty_docs]
pub type $fn_name<$($arg_name),*> = $struct_name<$(
<$arg_name as $crate::expression::AsExpression<$arg_type>>::Expression
),*>;
#[allow(non_camel_case_types)]
#[doc=$docs]
pub fn $fn_name<$($arg_name),*>($($arg_name: $arg_name),*)
-> $fn_name<$($arg_name),*>
where $($arg_name: $crate::expression::AsExpression<$arg_type>),+
{
$struct_name {
$($arg_name: $arg_name.as_expression()),+
}
}
#[allow(non_camel_case_types)]
impl<$($arg_name),*> $crate::expression::Expression for $struct_name<$($arg_name),*> where
for <'a> ($(&'a $arg_name),*): $crate::expression::Expression,
{
type SqlType = $return_type;
}
#[allow(non_camel_case_types)]
impl<$($arg_name),*, DB> $crate::query_builder::QueryFragment<DB> for $struct_name<$($arg_name),*> where
DB: $crate::backend::Backend,
for <'a> ($(&'a $arg_name),*): $crate::query_builder::QueryFragment<DB>,
{
fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
out.push_sql(concat!(stringify!($fn_name), "("));
$crate::query_builder::QueryFragment::walk_ast(
&($(&self.$arg_name),*), out.reborrow())?;
out.push_sql(")");
Ok(())
}
}
#[allow(non_camel_case_types)]
impl<$($arg_name),*, QS> $crate::expression::SelectableExpression<QS> for $struct_name<$($arg_name),*> where
$($arg_name: $crate::expression::SelectableExpression<QS>,)*
$struct_name<$($arg_name),*>: $crate::expression::AppearsOnTable<QS>,
{
}
#[allow(non_camel_case_types)]
impl<$($arg_name),*, QS> $crate::expression::AppearsOnTable<QS> for $struct_name<$($arg_name),*> where
$($arg_name: $crate::expression::AppearsOnTable<QS>,)*
$struct_name<$($arg_name),*>: $crate::expression::Expression,
{
}
#[allow(non_camel_case_types)]
impl<$($arg_name),*> $crate::expression::NonAggregate for $struct_name<$($arg_name),*> where
$($arg_name: $crate::expression::NonAggregate,)*
$struct_name<$($arg_name),*>: $crate::expression::Expression,
{
}
}
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "with-deprecated"))]
macro_rules! sql_function_body {
($($args:tt)*) => {
compile_error!(
"You are using a deprecated form of `sql_function!`. \
You must enable the `with-deprecated` feature on `diesel`."
);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_sql_function_body {
(
data = (
meta = $meta:tt,
fn_name = $fn_name:tt,
),
type_args = $type_args:tt,
type_args_with_bounds = $type_args_with_bounds:tt,
unparsed_tokens = (
$args:tt -> $return_type:ty $(;)*
),
) => {
__diesel_sql_function_body! {
meta = $meta,
fn_name = $fn_name,
type_args = $type_args,
type_args_with_bounds = $type_args_with_bounds,
args = $args,
return_type = $return_type,
}
};
(
meta = $meta:tt,
fn_name = $fn_name:ident,
$($rest:tt)*
) => {
__diesel_sql_function_body! {
aggregate = no,
sql_name = stringify!($fn_name),
unchecked_meta = $meta,
meta = (),
fn_name = $fn_name,
$($rest)*
}
};
(
aggregate = $aggregate:tt,
sql_name = $sql_name:expr,
unchecked_meta = (#[aggregate] $($unchecked:tt)*),
meta = $meta:tt,
$($rest:tt)*
) => {
__diesel_sql_function_body! {
aggregate = yes,
sql_name = $sql_name,
unchecked_meta = ($($unchecked)*),
meta = $meta,
$($rest)*
}
};
(
aggregate = $aggregate:tt,
sql_name = $ignored:expr,
unchecked_meta = (#[sql_name = $sql_name:expr] $($unchecked:tt)*),
meta = $meta:tt,
$($rest:tt)*
) => {
__diesel_sql_function_body! {
aggregate = $aggregate,
sql_name = $sql_name,
unchecked_meta = ($($unchecked)*),
meta = $meta,
$($rest)*
}
};
(
aggregate = $aggregate:tt,
sql_name = $sql_name:expr,
unchecked_meta = (#$checked:tt $($unchecked:tt)*),
meta = ($($meta:tt)*),
$($rest:tt)*
) => {
__diesel_sql_function_body! {
aggregate = $aggregate,
sql_name = $sql_name,
unchecked_meta = ($($unchecked)*),
meta = ($($meta)* #$checked),
$($rest)*
}
};
(
aggregate = $aggregate:tt,
sql_name = $sql_name:expr,
unchecked_meta = (),
meta = ($($meta:tt)*),
fn_name = $fn_name:ident,
type_args = ($($type_args:ident,)*),
type_args_with_bounds = ($($type_args_bounds:tt)*),
args = ($($arg_name:ident: $arg_type:ty),*),
return_type = $return_type:ty,
) => {
$($meta)*
#[allow(non_camel_case_types)]
pub fn $fn_name<$($type_args_bounds)* $($arg_name),*>($($arg_name: $arg_name),*)
-> $fn_name::HelperType<$($type_args,)* $($arg_name),*>
where
$($arg_name: $crate::expression::AsExpression<$arg_type>),+
{
$fn_name::$fn_name {
$($arg_name: $arg_name.as_expression(),)+
$($type_args: ::std::marker::PhantomData,)*
}
}
#[doc(hidden)]
#[allow(non_camel_case_types, non_snake_case, unused_imports)]
pub(crate) mod $fn_name {
use super::*;
use $crate::sql_types::*;
#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
pub struct $fn_name<$($type_args,)* $($arg_name),*> {
$(pub(in super) $arg_name: $arg_name,)*
$(pub(in super) $type_args: ::std::marker::PhantomData<$type_args>,)*
}
pub type HelperType<$($type_args,)* $($arg_name),*> = $fn_name<
$($type_args,)*
$(
<$arg_name as $crate::expression::AsExpression<$arg_type>>::Expression
),*
>;
impl<$($type_args_bounds)* $($arg_name),*>
$crate::expression::Expression
for $fn_name<$($type_args,)* $($arg_name),*>
where
($($arg_name),*): $crate::expression::Expression,
{
type SqlType = $return_type;
}
impl<$($type_args_bounds)* $($arg_name),*, DB>
$crate::query_builder::QueryFragment<DB>
for $fn_name<$($type_args,)* $($arg_name),*>
where
DB: $crate::backend::Backend,
for<'a> ($(&'a $arg_name),*): $crate::query_builder::QueryFragment<DB>,
{
fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
out.push_sql(concat!($sql_name, "("));
$crate::query_builder::QueryFragment::walk_ast(
&($(&self.$arg_name),*), out.reborrow())?;
out.push_sql(")");
Ok(())
}
}
impl<$($type_args_bounds)* $($arg_name),*, QS>
$crate::expression::SelectableExpression<QS>
for $fn_name<$($type_args,)* $($arg_name),*>
where
$($arg_name: $crate::expression::SelectableExpression<QS>,)*
Self: $crate::expression::AppearsOnTable<QS>,
{
}
impl<$($type_args_bounds)* $($arg_name),*, QS>
$crate::expression::AppearsOnTable<QS>
for $fn_name<$($type_args,)* $($arg_name),*>
where
$($arg_name: $crate::expression::AppearsOnTable<QS>,)*
Self: $crate::expression::Expression,
{
}
static_cond! {
if $aggregate == no {
impl<$($type_args_bounds)* $($arg_name),*>
$crate::expression::NonAggregate
for $fn_name<$($type_args,)* $($arg_name),*>
where
$($arg_name: $crate::expression::NonAggregate,)*
Self: $crate::expression::Expression,
{
}
}
}
__diesel_sqlite_register_fn! {
type_args = ($($type_args)*),
aggregate = $aggregate,
fn_name = $fn_name,
args = ($($arg_name,)+),
sql_args = ($($arg_type,)+),
ret = $return_type,
}
}
}
}
#[macro_export]
#[doc(hidden)]
#[cfg(feature = "sqlite")]
macro_rules! __diesel_sqlite_register_fn {
(
type_args = ($($type_args:tt)+),
$($rest:tt)*
) => {
};
(
type_args = $ignored:tt,
aggregate = yes,
$($rest:tt)*
) => {
};
(
type_args = (),
aggregate = no,
fn_name = $fn_name:ident,
args = ($($args:ident,)+),
sql_args = $sql_args:ty,
ret = $ret:ty,
) => {
#[allow(dead_code)]
pub fn register_impl<F, Ret, $($args,)+>(
conn: &$crate::SqliteConnection,
f: F,
) -> $crate::QueryResult<()>
where
F: Fn($($args,)+) -> Ret + Send + 'static,
($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>,
Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>,
{
conn.register_sql_function::<$sql_args, $ret, _, _, _>(
stringify!($fn_name),
true,
move |($($args,)+)| f($($args),+),
)
}
#[allow(dead_code)]
pub fn register_nondeterministic_impl<F, Ret, $($args,)+>(
conn: &$crate::SqliteConnection,
mut f: F,
) -> $crate::QueryResult<()>
where
F: FnMut($($args,)+) -> Ret + Send + 'static,
($($args,)+): $crate::deserialize::Queryable<$sql_args, $crate::sqlite::Sqlite>,
Ret: $crate::serialize::ToSql<$ret, $crate::sqlite::Sqlite>,
{
conn.register_sql_function::<$sql_args, $ret, _, _, _>(
stringify!($fn_name),
false,
move |($($args,)+)| f($($args),+),
)
}
};
}
#[macro_export]
#[doc(hidden)]
#[cfg(not(feature = "sqlite"))]
macro_rules! __diesel_sqlite_register_fn {
($($token:tt)*) => {};
}
#[macro_export]
macro_rules! sql_function {
($(#$meta:tt)* fn $fn_name:ident $args:tt $(;)*) => {
sql_function!($(#$meta)* fn $fn_name $args -> ());
};
($(#$meta:tt)* fn $fn_name:ident $args:tt -> $return_type:ty $(;)*) => {
sql_function!($(#$meta)* fn $fn_name <> $args -> $return_type);
};
(
$(#$meta:tt)*
fn $fn_name:ident
<
$($tokens:tt)*
) => {
__diesel_parse_type_args!(
data = (
meta = ($(#$meta)*),
fn_name = $fn_name,
),
callback = __diesel_sql_function_body,
tokens = ($($tokens)*),
);
};
($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty) => {
sql_function!($fn_name, $struct_name, $args -> $return_type, "");
};
($fn_name:ident, $struct_name:ident, $args:tt -> $return_type:ty, $docs:expr) => {
sql_function!($fn_name, $struct_name, $args -> $return_type, $docs, "");
};
($fn_name:ident, $struct_name:ident, ($($arg_name:ident: $arg_type:ty),*)) => {
sql_function!($fn_name, $struct_name, ($($arg_name: $arg_type),*) -> ());
};
(
$fn_name:ident,
$struct_name:ident,
$args:tt -> $return_type:ty,
$docs:expr,
$helper_ty_docs:expr
) => {
sql_function_body!($fn_name, $struct_name, $args -> $return_type, $docs, $helper_ty_docs);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! no_arg_sql_function_body_except_to_sql {
($type_name:ident, $return_type:ty, $docs:expr) => {
#[allow(non_camel_case_types)]
#[doc=$docs]
#[derive(Debug, Clone, Copy, QueryId)]
pub struct $type_name;
impl $crate::expression::Expression for $type_name {
type SqlType = $return_type;
}
impl<QS> $crate::expression::SelectableExpression<QS> for $type_name {}
impl<QS> $crate::expression::AppearsOnTable<QS> for $type_name {}
impl $crate::expression::NonAggregate for $type_name {}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! no_arg_sql_function_body {
($type_name:ident, $return_type:ty, $docs:expr, $($constraint:ident)::+) => {
no_arg_sql_function_body_except_to_sql!($type_name, $return_type, $docs);
impl<DB> $crate::query_builder::QueryFragment<DB> for $type_name where
DB: $crate::backend::Backend + $($constraint)::+,
{
fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
out.push_sql(concat!(stringify!($type_name), "()"));
Ok(())
}
}
};
($type_name:ident, $return_type:ty, $docs:expr) => {
no_arg_sql_function_body_except_to_sql!($type_name, $return_type, $docs);
impl<DB> $crate::query_builder::QueryFragment<DB> for $type_name where
DB: $crate::backend::Backend,
{
fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
out.push_sql(concat!(stringify!($type_name), "()"));
Ok(())
}
}
};
}
#[macro_export]
macro_rules! no_arg_sql_function {
($type_name:ident, $return_type:ty) => {
no_arg_sql_function!($type_name, $return_type, "");
};
($type_name:ident, $return_type:ty, $docs:expr) => {
no_arg_sql_function_body!($type_name, $return_type, $docs);
};
($type_name:ident, $return_type:ty, $docs:expr, $($constraint:ident)::+) => {
no_arg_sql_function_body!($type_name, $return_type, $docs, $($constraint)::+);
};
}
pub mod aggregate_folding;
pub mod aggregate_ordering;
pub mod date_and_time;
pub mod helper_types;