udf_macros/
lib.rs

1#![warn(
2    clippy::pedantic,
3    clippy::nursery,
4    clippy::str_to_string,
5    clippy::missing_inline_in_public_items
6)]
7// Pedantic config
8#![allow(
9    clippy::missing_const_for_fn,
10    clippy::missing_panics_doc,
11    clippy::must_use_candidate,
12    clippy::cast_possible_truncation
13)]
14
15mod register;
16mod types;
17
18use proc_macro::TokenStream;
19
20macro_rules! match_variant {
21    ($variant:path) => {
22        |x| {
23            if let $variant(value) = x {
24                Some(value)
25            } else {
26                None
27            }
28        }
29    };
30}
31
32pub(crate) use match_variant;
33
34/// # Register exposed function names required for a UDF
35///
36/// This macro is applied to an `impl BasicUdf` block (and an `AggregateUdf`
37/// block, if applicable) and exposed the C-callable functions that
38/// `MariaDB`/`MySQL` expect.
39///
40/// Usage:
41///
42/// ```ignore
43/// #[register]
44/// impl BasicUdf for MyStruct {
45///     ...
46/// }
47///
48/// #[register]
49/// impl AggregateUdf for MyStruct {
50///     ...
51/// }
52/// ```
53///
54/// Its process is as follows:
55///
56/// - Convert the implemented struct's name to snake case to create the function
57///   name (unless a name is specified)
58/// - Obtain the return type from the `Returns` type in `BasicUdf`
59/// - Create functions `fn_name`, `fn_name_init`, and `fn_name_deinit` with
60///   correct signatures and interfaces
61/// - If applied on an `impl AggregateUdf` block, create `fn_name_clear` and
62///   `fn_name_add`. `fn_name_remove` is also included if it is redefined
63///
64/// # Arguments
65///
66/// - `#[udf::register(name = "new_name")]` will specify a name for your SQL
67///   function. If this is not specified, your struct name will be converted to
68///   snake case and used (e.g. `AddAllNumbers` would become `add_all_numbers`
69///   by default).
70/// - `#[udf::register(alias = "alias")]` will specify an alias for this function.
71///   More than one alias can be specified, and it can be combined with a `name` attribute.
72///
73/// **IMPORTANT**: if using aggregate UDFs, the exact same renaming must be applied to
74/// both the `impl BasicUdf` and the `impl AggregateUdf` blocks! If this is not followed,
75/// your function will not act as an aggregate (there may also be a compile error).
76#[proc_macro_attribute]
77pub fn register(args: TokenStream, item: TokenStream) -> TokenStream {
78    // Keep this file clean by keeping the dirty work in entry
79    register::register(&args, item)
80}