mz_expr_derive/
lib.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Proc macros to derive SQL function traits.
11
12/// Derive function traits for SQL functions.
13///
14/// The `sqlfunc` attribute macro is used to derive SQL function traits for unary and binary
15/// functions. Depending on the kind of function, it will implement the appropriate traits.
16/// For unary functions, it implements the `EagerUnaryFunc` trait, and for binary functions,
17/// it implements the `EagerBinaryFunc` trait.
18///
19/// The macro takes the following arguments:
20/// * `is_monotone`: An expression indicating whether the function is monotone. For unary functions,
21///   it should be an expression that evaluates to a boolean. For binary functions, it should be a
22///   tuple of two expressions, each evaluating to a boolean. See `LazyBinaryFunc` for details.
23/// * `sqlname`: The SQL name of the function.
24/// * `preserves_uniqueness`: A boolean indicating whether the function preserves uniqueness.
25///   Unary functions only.
26/// * `inverse`: A function that is the inverse of the function. Applies to unary functions only.
27/// * `negate`: A function that negates the function. Applies to binary functions only. For example,
28///   the `!=` operator is the negation of the `=` operator, and we'd mark the `Eq` function with
29///   `negate = Some(BinaryFunc::NotEq)`.
30/// * `is_infix_op`: A boolean indicating whether the function is an infix operator. Applies to
31///   binary functions only.
32/// * `output_type`: The output type of the function.
33/// * `output_type_expr`: An expression that evaluates to the output type. Applies to binary
34///   functions only. The expression has access to the `input_type_a` and `input_type_b` variables,
35///   and should evaluate to a `SqlColumnType` value. Requires `introduces_nulls`, and conflicts with
36///   `output_type`.
37/// * `could_error`: A boolean indicating whether the function could error.
38/// * `propagate_nulls`: A boolean indicating whether the function propagates nulls. Applies to
39///   binary functions only. If not specified, use the default implementation from the trait.
40///   The default is to return true if all input types are not-nullable.
41/// * `introduces_nulls`: A boolean indicating whether the function introduces nulls. Applies to
42///   all functions. If not specified, use the default implementation from the trait.
43///   The default is to return the `nullable` property of the output type.
44///
45/// # Limitations
46/// * The input and output types can contain lifetime parameters, as long as they are `'a`.
47/// * Unary functions cannot yet receive a `&RowArena` as an argument.
48/// * The `output_type`
49///
50/// # Examples
51/// ```ignore
52/// use mz_expr_derive::sqlfunc;
53/// #[sqlfunc(sqlname = "!")]
54/// fn negate(a: bool) -> bool {
55///    !a
56/// }
57/// ```
58#[proc_macro_attribute]
59pub fn sqlfunc(
60    attr: proc_macro::TokenStream,
61    item: proc_macro::TokenStream,
62) -> proc_macro::TokenStream {
63    mz_expr_derive_impl::sqlfunc(attr.into(), item.into(), true)
64        .unwrap_or_else(|err| err.write_errors())
65        .into()
66}