@@ -260,10 +260,94 @@ macro_rules! __diesel_sql_function_body {
260260 }
261261 }
262262 }
263+
264+ __diesel_sqlite_register_fn! {
265+ type_args = ( $( $type_args) * ) ,
266+ fn_name = $fn_name,
267+ args = ( $( $arg_name, ) +) ,
268+ sql_args = ( $( $arg_type, ) +) ,
269+ ret = $return_type,
270+ }
263271 }
264272 }
265273}
266274
275+ #[ macro_export]
276+ #[ doc( hidden) ]
277+ #[ cfg( feature = "sqlite" ) ]
278+ macro_rules! __diesel_sqlite_register_fn {
279+ // We can't handle generic functions for SQLite
280+ (
281+ type_args = ( $( $type_args: tt) +) ,
282+ $( $rest: tt) *
283+ ) => {
284+ } ;
285+
286+ (
287+ type_args = ( ) ,
288+ fn_name = $fn_name: ident,
289+ args = ( $( $args: ident, ) +) ,
290+ sql_args = $sql_args: ty,
291+ ret = $ret: ty,
292+ ) => {
293+ #[ allow( dead_code) ]
294+ /// Registers an implementation for this function on the given connection
295+ ///
296+ /// This function must be called for every `SqliteConnection` before
297+ /// this SQL function can be used on SQLite. The implementation must be
298+ /// deterministic (returns the same result given the same arguments). If
299+ /// the function is nondeterministic, call
300+ /// `register_nondeterministic_impl` instead.
301+ pub fn register_impl<F , Ret , $( $args, ) +>(
302+ conn: & $crate:: SqliteConnection ,
303+ f: F ,
304+ ) -> $crate:: QueryResult <( ) >
305+ where
306+ F : Fn ( $( $args, ) +) -> Ret + Send + ' static ,
307+ ( $( $args, ) +) : $crate:: deserialize:: Queryable <$sql_args, $crate:: sqlite:: Sqlite >,
308+ Ret : $crate:: serialize:: ToSql <$ret, $crate:: sqlite:: Sqlite >,
309+ {
310+ conn. register_sql_function:: <$sql_args, $ret, _, _, _>(
311+ stringify!( $fn_name) ,
312+ true ,
313+ move |( $( $args, ) +) | f( $( $args) ,+) ,
314+ )
315+ }
316+
317+ #[ allow( dead_code) ]
318+ /// Registers an implementation for this function on the given connection
319+ ///
320+ /// This function must be called for every `SqliteConnection` before
321+ /// this SQL function can be used on SQLite.
322+ /// `register_nondeterministic_impl` should only be used if your
323+ /// function can return different results with the same arguments (e.g.
324+ /// `random`). If your function is deterministic, you should call
325+ /// `register_impl` instead.
326+ pub fn register_nondeterministic_impl<F , Ret , $( $args, ) +>(
327+ conn: & $crate:: SqliteConnection ,
328+ mut f: F ,
329+ ) -> $crate:: QueryResult <( ) >
330+ where
331+ F : FnMut ( $( $args, ) +) -> Ret + Send + ' static ,
332+ ( $( $args, ) +) : $crate:: deserialize:: Queryable <$sql_args, $crate:: sqlite:: Sqlite >,
333+ Ret : $crate:: serialize:: ToSql <$ret, $crate:: sqlite:: Sqlite >,
334+ {
335+ conn. register_sql_function:: <$sql_args, $ret, _, _, _>(
336+ stringify!( $fn_name) ,
337+ false ,
338+ move |( $( $args, ) +) | f( $( $args) ,+) ,
339+ )
340+ }
341+ } ;
342+ }
343+
344+ #[ macro_export]
345+ #[ doc( hidden) ]
346+ #[ cfg( not( feature = "sqlite" ) ) ]
347+ macro_rules! __diesel_sqlite_register_fn {
348+ ( $( $token: tt) * ) => { } ;
349+ }
350+
267351#[ macro_export]
268352/// Declare a sql function for use in your code.
269353///
@@ -325,7 +409,7 @@ macro_rules! __diesel_sql_function_body {
325409/// Most attributes given to this macro will be put on the generated function
326410/// (including doc comments).
327411///
328- /// # Example
412+ /// # Adding Doc Comments
329413///
330414/// ```no_run
331415/// # #[macro_use] extern crate diesel;
@@ -350,6 +434,8 @@ macro_rules! __diesel_sql_function_body {
350434/// # }
351435/// ```
352436///
437+ /// # Special Attributes
438+ ///
353439/// There are a handful of special attributes that Diesel will recognize. They
354440/// are:
355441///
@@ -382,6 +468,49 @@ macro_rules! __diesel_sql_function_body {
382468/// crates.select(sum(id));
383469/// # }
384470/// ```
471+ ///
472+ /// # Use with SQLite
473+ ///
474+ /// On most backends, the implementation of the function is defined in a
475+ /// migration using `CREATE FUNCTION`. On SQLite, the function is implemented in
476+ /// Rust instead. You must call `register_impl` or
477+ /// `register_nondeterministic_impl` with every connection before you can use
478+ /// the function.
479+ ///
480+ /// These functions will only be generated if the `sqlite` feature is enabled,
481+ /// and the function is not generic. Generic functions and variadic functions
482+ /// are not supported on SQLite.
483+ ///
484+ /// ```rust
485+ /// # #[macro_use] extern crate diesel;
486+ /// # use diesel::*;
487+ /// #
488+ /// # #[cfg(feature = "sqlite")]
489+ /// # fn main() {
490+ /// # run_test().unwrap();
491+ /// # }
492+ /// #
493+ /// # #[cfg(not(feature = "sqlite"))]
494+ /// # fn main() {
495+ /// # }
496+ /// #
497+ /// use diesel::sql_types::{Integer, Double};
498+ /// sql_function!(fn add_mul(x: Integer, y: Integer, z: Double) -> Double);
499+ ///
500+ /// # #[cfg(feature = "sqlite")]
501+ /// # fn run_test() -> Result<(), Box<::std::error::Error>> {
502+ /// let connection = SqliteConnection::establish(":memory:")?;
503+ ///
504+ /// add_mul::register_impl(&connection, |x: i32, y: i32, z: f64| {
505+ /// (x + y) as f64 * z
506+ /// })?;
507+ ///
508+ /// let result = select(add_mul(1, 2, 1.5))
509+ /// .get_result::<f64>(&connection)?;
510+ /// assert_eq!(4.5, result);
511+ /// # Ok(())
512+ /// # }
513+ /// ```
385514macro_rules! sql_function {
386515 ( $( #$meta: tt) * fn $fn_name: ident $args: tt $( ; ) * ) => {
387516 sql_function!( $( #[ $meta] ) * fn $fn_name $args -> ( ) ) ;
0 commit comments