User-defined functions
User-Defined Functions (UDFs) allow you to extend FeatureQL language capabilities by implementing custom functions in the target language.
There are typically two main types of User-Defined Functions (UDFs):
Scalar UDFs
- Takes one or more input parameters and returns a single value
- Executes once for each row in the result set
- Common use cases: string manipulation, custom calculations, data transformations
- Example: Creating a function to format phone numbers or calculate age from birthdate
Table-Valued UDFs (TVFs)
- Returns a table result set rather than a single value
- Can process multiple rows and return multiple columns
- Often used for more complex data transformations or business logic
- Example: A function that takes a date range and returns a detailed sales analysis
While the UDF capability supports only Scalar UDFs and is currently experimental, it provides powerful customization options through configurations and templating.
Implementing a UDF
To create a UDF, you'll need to provide a JSON configuration dictionary with the following required fields:
positions
: Maps positional arguments to named parametersvariants
: Defines the supported function signatures (input and output types)template_{target}
: Specifies transpilation rules for different systems (supported: featureql, trino, duckdb, datafusion)
UDFs in action
Here's an example that implements a custom normalized_quarter() function:
This configuration:
- Defines a function taking a date or timestamp as an argument
- Returns a string representing the normalized quarter
- Uses Jinja2 syntax for template-based transpilation
Avoid UDFs when possible
Avoid creating UDFs when native FeatureQL functions can achieve almost the same result.
For example, the normalized_quarter() function above could be written as a regular feature. UDFs is just useful to support polymorphism here.
or even a macro: