Search Shortcut cmd + k | ctrl + k
func_apply

Dynamic function invocation - call any scalar function or macro by name at runtime

Maintainer(s): teaguesterling

Compatibility Matrix

This table covers all DuckDB releases that have not reached end-of-life, including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.

Platform 1.4.4 1.4.5 1.5.5 1.5.6 2.0.0
Linux AMD64
Linux ARM64
macOS AMD64
macOS ARM64
Windows AMD64
Windows ARM64
WebAssembly

Installing and Loading

INSTALL func_apply FROM community;
LOAD func_apply;

Example

-- Load the extension
LOAD func_apply;

-- Call scalar functions dynamically
SELECT apply('upper', 'hello world');
-- Result: HELLO WORLD

SELECT apply('substr', 'hello world', 7, 5);
-- Result: world

-- Call table functions dynamically
SELECT * FROM apply_table('range', 5);
-- Returns: 0, 1, 2, 3, 4

SELECT * FROM apply_table('generate_series', 1, 10, 2);
-- Returns: 1, 3, 5, 7, 9

-- Check if a function exists before calling
SELECT function_exists('my_custom_func');
-- Result: true/false

About func_apply

The FuncApply extension enables dynamic function invocation in DuckDB, allowing you to call any scalar function or macro by name at runtime. This is useful for data-driven transformations, dynamic SQL generation, and building flexible data pipelines.

Functions

Function Description
apply(func_name, ...args) Call a function by name with arguments
apply_with(func_name, args, kwargs) Call a function with arguments as a list
apply_table(func_name, ...args) Call a table function by name with arguments
apply_table_with(func_name, args, kwargs) Call a table function with arguments as a list
func_dispatch(routes, key, ...args) Dispatch to the function named by routes[key], with real return types
function_exists(name) Check if a function exists

Use Cases

Data-Driven Transformations

-- Store transformation rules in a table
CREATE TABLE transforms (column_name VARCHAR, func_name VARCHAR);
INSERT INTO transforms VALUES ('name', 'upper'), ('email', 'lower');

-- Apply transformations dynamically
SELECT apply(t.func_name, d.value) as result
FROM data d JOIN transforms t ON d.column = t.column_name;

Routing With func_dispatch

CREATE MACRO clean_git(p)   AS regexp_replace(p, '^git://', '');
CREATE MACRO clean_http(p)  AS regexp_replace(p, '^https?://', '');
CREATE MACRO clean_other(p) AS p;

SELECT func_dispatch(MAP{'git':   'clean_git',
                         'https': 'clean_http',
                         '*':     'clean_other'},
                     split_part(url, ':', 1),
                     url) AS cleaned
FROM urls;

The '*' entry catches any key the map does not name. Unlike apply() with a function name that is not a constant, func_dispatch binds every candidate in a constant routing map at plan time, so the result keeps its real type instead of collapsing to VARCHAR:

CREATE MACRO pair(x) AS [x, x];
SELECT typeof(func_dispatch(MAP{'a': 'pair'}, 'a', 7));  -- INTEGER[]

All routes in a constant map must accept the forwarded arguments, and the session security policy applies to every route including '*'.

Dynamic Function Selection

-- Choose function based on data type
SELECT apply(
    CASE typeof(value)
        WHEN 'VARCHAR' THEN 'upper'
        WHEN 'INTEGER' THEN 'abs'
    END,
    value
) FROM my_table;

Supported Function Types

  • Scalar functions (e.g., upper, abs, substr)
  • Macros (e.g., list_sum, list_reverse)

Aggregate and table functions are not supported.

Security Model

apply and apply_table run on the caller's own context — they add no privilege beyond the SQL the caller could already execute directly. They are a dynamic-dispatch convenience, not a sandbox.

For scenarios that embed func_apply and want to restrict which functions can be invoked (e.g. accepting a function name from less-trusted input), an optional, opt-in policy is available. It is per session and defaults to none (no restriction):

Function Description
func_apply_set_security_mode(mode) 'none', 'blacklist', 'whitelist', or 'validator'
func_apply_set_whitelist([...]) / func_apply_set_blacklist([...]) Set the allowed/denied function names
func_apply_lock_security() Irreversibly lock the current session's policy

The policy lives on the session's ClientContext and does not leak across connections. Versions before 0.2.0 stored it process-globally and could quote-escape injected identifiers — see security advisory GHSA-55g5-vp25-phpg; upgrade to 0.2.0 (DuckDB v1.5.4 track).

Added Functions

function_name function_type description comment examples
apply scalar NULL NULL  
apply_table table Dynamically invoke a table function by name with variable arguments. NULL [SELECT * FROM apply_table('range', 5)]
apply_table_with table Dynamically invoke a table function with structured args and kwargs. NULL [SELECT * FROM apply_table_with('range', args := [5])]
apply_with scalar Dynamically invoke a scalar function with a list of positional args and struct of kwargs. NULL [apply_with('upper', args := ['hello'])]
func_apply_get_security_config scalar Get the current security configuration as a JSON string. NULL [func_apply_get_security_config()]
func_apply_lock_security scalar Lock the current security configuration to prevent further modifications. NULL [func_apply_lock_security()]
func_apply_set_blacklist scalar Set the list of disallowed functions in blacklist security mode. NULL [func_apply_set_blacklist(['system', 'read_csv'])]
func_apply_set_block_default scalar Set the default return value when a blocked function is encountered. NULL [func_apply_set_block_default('BLOCKED')]
func_apply_set_on_block scalar Set behavior when a blocked function is called ('error', 'null', or 'default'). NULL [func_apply_set_on_block('error')]
func_apply_set_security_mode scalar Set the security mode for dynamic function execution ('permissive', 'whitelist', or 'blacklist'). NULL [func_apply_set_security_mode('permissive')]
func_apply_set_validator scalar Set a custom SQL validator function to check candidate function invocations. NULL [func_apply_set_validator('my_validator')]
func_apply_set_whitelist scalar Set the list of allowed functions in whitelist security mode. NULL [func_apply_set_whitelist(['upper', 'lower', 'abs'])]
func_dispatch scalar Dispatch to the function named by routes[key], forwarding the remaining arguments. NULL [func_dispatch(MAP {'a': 'upper', '*': 'lower'}, 'a', 'hello')]
function_exists scalar Check if a function exists in the catalog. NULL [function_exists('upper')]

Overloaded Functions

This extension does not add any function overloads.

Added Types

This extension does not add any types.

Added Settings

This extension does not add any settings.