WebAssembly User-Defined Functions

### Delete a module[​](#delete-a-module "Direct link to Delete a module")

Deletion performed by `DELETE FROM system.webassembly_modules WHERE name = '...'` statement.
Only deletion of single module by exact name per single statement is supported.

```
DELETE FROM system.webassembly_modules WHERE name = 'collatz';
```

If any existing UDFs reference the module, the deletion fails, so you must drop those UDFs first.

## Create a WebAssembly UDF[​](#create-a-webassembly-udf "Direct link to Create a WebAssembly UDF")

**Syntax**:

```
CREATE [OR REPLACE] FUNCTION function_name
LANGUAGE WASM
FROM 'module_name' [:: 'source_function_name']
ARGUMENTS ( [name type[, ...]] | [type[, ...]] )
RETURNS return_type
[ABI ROW_DIRECT | ABI BUFFERED_V1]
[SHA256_HASH 'hex']
[SETTINGS key = value[, ...]];
```

**Parameters**:

- `function_name`: Name of the function in ClickHouse. May be different from the exported function name in the module.
- `FROM 'module_name' :: 'source_function_name'`: Name of the loaded WASM module and function name in WASM module to use (defaults to function\_name)
- `ARGUMENTS`: List of argument names and types (names optional and used for serialization formats that support named fields)
- `ABI`: Application Binary Interface version
  - `ROW_DIRECT`: Direct type mapping, row-by-row processing
  - `BUFFERED_V1`: Block-based processing with serialization
- `SHA256_HASH`: Expected module hash for verification (auto-filled if omitted), can be used to ensure the correct WASM module loaded across different replicas.
- `SETTINGS`: Per-function settings
  - `serialization_format` String — Serialization format for ABI requires it. Default: `MsgPack`.

## ABIs Versions[​](#abis-versions "Direct link to ABIs Versions")

To interact with ClickHouse, WebAssembly modules must adhere to one of the supported ABIs (Application Binary Interfaces).

- `ROW_DIRECT`: Direct type mapping (primitive types `Int32`, `UInt32`, `Int64`, `UInt64`, `Float32`, `Float64` only)
- `BUFFERED_V1`: Complex types with serialization

### ABI ROW\_DIRECT[​](#abi-row_direct "Direct link to ABI ROW_DIRECT")

Calls an exported WASM function directly per row.

- Arguments and return types as numeric types `Int32/UInt32/Int64/UInt64/Float32/Float64/Int128/UInt128`.
- Strings are not supported in this ABI.
- Signatures must match the WASM export (`i32/i64/f32/f64/v128`).
- No support functions required to be exported by the module.

For example function with signature:

```
(func (param i32 i64 f32) (result f64) ...)
```

Can be created as:

```
CREATE FUNCTION my_func ARGUMENTS (Int32, UInt64, Float32) RETURNS Float64 ...
```

WebAssembly does not distinguish between signed and unsigned arguments, but rather uses different instructions to interpret the values. Thus, size of the argument should match exactly, while signedness is determined by the operations inside the function.

### ABI BUFFERED\_V1[​](#abi-buffered_v1 "Direct link to ABI BUFFERED_V1")

Note

This ABI is experimental and subject to change in future releases.

Processes entire blocks at once using a (de)serialization through WASM memory. Supports any argument and return types.

Serialized data is copied to wasm memory passed as pointer to buffer (which consists of pointer to data and size of the data) to the UDF function along with the number of rows in the input. Thus, user-defined function on wasm time always accepts two `i32` arguments and returns single `i32` value.
Guest code processes the data and returns a pointer to the result buffer with serialized result data.

The guest code must provide two functions to create and destroy these buffers.

```
(module
  ;; Allocate a new buffer of specified size
  ;; Returns: handle to Buffer structure (not direct data pointer!) with pointer to data and size
  (func (export "clickhouse_create_buffer")
    (param $size i32)    ;; Size of data to allocate
    (result i32))        ;; Returns buffer handle with enough space

  ;; Free a buffer by its handle
  (func (export "clickhouse_destroy_buffer")
    (param $handle i32)  ;; Buffer handle to free
    (result))            ;; No return value

    ;; User-defined function
    (func (export "user_defined_function1")
      (param $input_buffer_handle i32)  ;; Input buffer handle
      (param $n i32)                    ;; Number of rows in input
      (result i32))                     ;; Returns output buffer handle
)
```

Example C definitions:

```
typedef struct {
    uint8_t * data;
    uint32_t size;
} ClickhouseBuffer;

ClickhouseBuffer * clickhouse_create_buffer(uint32_t size) { /* ... */ }

void clickhouse_destroy_buffer(ClickhouseBuffer * data) { /* ... */ }

/// Example user-defined functions
ClickhouseBuffer * user_defined_function1(ClickhouseBuffer * span, uint32_t n) { /* ... */ }
ClickhouseBuffer * user_defined_function2(ClickhouseBuffer * span, uint32_t n) { /* ... */ }
```

### Note for developing UDFs in Rust[​](#note-for-developing-udfs-in-rust "Direct link to Note for developing UDFs in Rust")

For Rust programs we provide a helper crate [clickhouse-wasm-udf](https://crates.io/crates/clickhouse-wasm-udf) to simplify development of WebAssembly UDFs for ClickHouse. The crate provides function for memory management, so you don't need to implement `clickhouse_create_buffer` and `clickhouse_destroy_buffer` functions manually, but rather add the crate as a dependency. Also there are macros `#[clickhouse_wasm_udf]` to wrap your regular Rust functions into the required ABI format.

With the crate you can write UDFs like this:

```
use clickhouse_wasm_udf_bindgen::clickhouse_udf;

#[clickhouse_udf]
pub fn some_udf(data: String) -> HashMap<String, String> {
    // Your implementation here
}
```

Macros will generate wrapper function accepting and returning buffer structures and handle serialization/deserialization automatically using `serde`.

## Host API available to modules[​](#host-api-available-to-modules "Direct link to Host API available to modules")

The following host functions may be imported and used by modules:

- `clickhouse_server_version() -> i64` — returns ClickHouse server version as integer (e.g. 25011001 for v25.11.1.1).
- `clickhouse_throw(ptr: i32, size: i32)` — throws an error with the provided message. Accepts pointer to the memory location containing the error message string and size of the string.
- `clickhouse_log(ptr: i32, size: i32)` — logs a message to ClickHouse server text log.
- `clickhouse_random(ptr: i32, size: i32)` — fills memory with random bytes.

## Settings[​](#settings "Direct link to Settings")

The following query-level settings control WebAssembly UDF execution:

- `webassembly_udf_max_fuel` — Fuel limit per WebAssembly UDF instance execution. Each WebAssembly instruction consumes some amount of fuel. Set to 0 for no limit.
- `webassembly_udf_max_memory` — Memory limit in bytes per WebAssembly UDF instance.
- `webassembly_udf_max_input_block_size` — Maximum number of rows passed to a WebAssembly UDF in a single block. Set to 0 to process all rows at once.
- `webassembly_udf_max_instances` — Maximum number of WebAssembly UDF instances that can run in parallel per function.

Example usage:

```
SET webassembly_udf_max_fuel = 200000;
SELECT my_wasm_udf(column) FROM table;
```

## See also[​](#see-also "Direct link to See also")

- [ClickHouse UDF overview](/docs/sql-reference/functions/udf)

- [Overview](#overview)- [Prerequisites](#prerequisites)- [Quick Start](#quick-start)- [Manage WASM modules via system table](#manage-wasm-modules-via-system-table)
        - [Insert a module](#insert-a-module)- [List modules](#list-modules)- [Delete a module](#delete-a-module)- [Create a WebAssembly UDF](#create-a-webassembly-udf)- [ABIs Versions](#abis-versions)
            - [ABI ROW\_DIRECT](#abi-row_direct)- [ABI BUFFERED\_V1](#abi-buffered_v1)- [Note for developing UDFs in Rust](#note-for-developing-udfs-in-rust)- [Host API available to modules](#host-api-available-to-modules)- [Settings](#settings)- [See also](#see-also)

Was this page helpful?