Crate udf

source ·
Expand description

A wrapper crate to make writing SQL user-defined functions (UDFs) easy

This crate provides bindings for easy creation of SQL user-defined functions in Rust. See the readme for more background information on how UDFs work in general.

Usage

Using this crate is fairly simple: create a struct that will be used to share data among UDF function calls (which can be zero-sized), then implement needed traits for it. BasicUdf provides function signatures for standard UDFs, and AggregateUdf provides signatures for aggregate (and window) UDFs. See the documentation there for a step-by-step guide.

use udf::prelude::*;

// Our struct that will produce a UDF of name `my_udf`
// If there is no data to store between calls, it can be zero sized
struct MyUdf;

#[register]
impl BasicUdf for MyUdf {
    // Specify return type of this UDF to be a nullable integer
    type Returns<'a> = Option<i64>;

    // Perform initialization steps here
    fn init(cfg: &UdfCfg<Init>, args: &ArgList<Init>) -> Result<Self, String> {
        todo!();
    }

    // Create a result here
    fn process<'a>(
        &'a mut self,
        cfg: &UdfCfg<Process>,
        args: &ArgList<Process>,
        error: Option<NonZeroU8>,
    ) -> Result<Self::Returns<'a>, ProcessError> {
        todo!();
    }
}

Building & Usage

The above example will create three C-callable functions: my_udf, my_udf_init, and my_udf_deinit, which is what MariaDB and MySql expect for UDFs. To create a C dynamic library (as is required for usage), add the following to your Cargo.toml

[lib]
crate-type = ["cdylib"]

The next time you run cargo build --release, in target/release there will be a shared library .so file. Copy this to your plugin_dir location (usually /usr/lib/mysql/plugin/), and load the function with the following:

CREATE FUNCTION my_udf RETURNS integer SONAME 'libudf_test.so';

Replace my_udf with the function name, integer with the return type, and libudf_test.so with the correct file name.

More details on building are discussed in the project readme. See the MariaDB documentation for more detailed information on how to load the created libraries.

Crate Features

This crate includes some optional features. They can be enabled in your Cargo.toml.

  • mock: enable this feature to add the mock module for easier unit testing. (note: this feature will become unneeded in the future and mock will be available by default. It is currently feature-gated because it is considered unstable.)
  • logging-debug: enable this feature to turn on debug level logging for this crate. This uses the udf_log! macro and includes information about memory management and function calls. These will show up with your SQL server logs.
  • logging-debug-calls full debugging printing of the structs passed between this library and the SQL server. Implies logging-debug.

Version Note

Because of reliance on a feature called GATs, this library requires Rust version >= 1.65. This only became stable on 2022-11-03; if you encounter issues compiling, be sure to update your toolchain.

Modules

Mocks of argument types found in this library, available with the feature mock
Module that can be imported with use udf::prelude::*; to quickly get the most often used imports.
Module containing traits to be implemented by a user
Types that represent SQL interfaces

Macros

Helper macro to create a MockArgList
Print a formatted log message to stderr to display in server logs

Structs

A collection of SQL arguments
Typestate marker for the initialization phase
Iterator over arguments in a ArgList
Typestate marker for the processing phase
A zero-sized struct indicating that something went wrong
A single SQL argument, including its attributes
A collection of SQL arguments

Enums

Helpful constants related to the max_length parameter
A possible SQL result consisting of a type and nullable value
Enum representing possible SQL result types

Constants

Max error message size, 0x200 = 512 bytes
Minimum size of a buffer for string results

Traits

This trait must be implemented if this function performs aggregation.
This trait specifies the functions needed for a standard (non-aggregate) UDF
A state of the UDF, representing either Init or Process

Attribute Macros

Register exposed function names required for a UDF