> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-trino-dialect.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentação para Funções Definidas pelo Usuário em WebAssembly

# Funções Definidas pelo Usuário em WebAssembly

export const ExperimentalBadge = () => {
  return <a href="https://clickhouse.com/docs/reference/settings/beta-and-experimental-features#experimental-features" className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            Recurso experimental
        </a>;
};

export const CloudNotSupportedBadge = () => {
  return <a href="https://clickhouse.com/docs/products/cloud/guides/cloud-compatibility#list-of-unsupported-features" className="cloudNotSupportedBadge">
            <div className="cloudNotSupportedIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.5" d="M6.33366 12.6666L12.3739 12.6667C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00003 12.3739 8.00003C12.3739 8.00003 12.3337 7.66659 12.0003 7.33325M10.667 5.33322C8.00033 2.33325 4.45395 4.78537 4.14195 6.68203C2.55728 6.7627 1.29395 8.06203 1.29395 9.6667C1.29395 11.3234 2.66699 12.6666 4.00033 12.6666" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.5" d="M2.66699 14L12.0003 4.66663" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

        </div>
            Sem suporte no ClickHouse Cloud
        </a>;
};

O ClickHouse oferece suporte à criação de funções definidas pelo usuário (UDFs) escritas em WebAssembly. Isso permite executar lógica personalizada escrita em linguagens como Rust, C, C++ ou outras, ao compilá-las em módulos WebAssembly.

<CloudNotSupportedBadge />

<ExperimentalBadge />

<div id="overview">
  ## Visão geral
</div>

Um módulo WebAssembly é um arquivo binário compilado que contém uma ou mais funções que podem ser chamadas pelo ClickHouse.
Pense em um módulo como uma biblioteca ou objeto compartilhado que você carrega uma vez e reutiliza muitas vezes.

Um módulo WebAssembly que contém UDFs pode ser escrito em qualquer linguagem que possa ser compilada para WebAssembly, como Rust, C ou C++.

O código compilado para WebAssembly (código "guest") e executado pelo ClickHouse ("host") roda em um ambiente isolado, com acesso apenas a um espaço de memória dedicado.

O código guest exporta funções que o ClickHouse pode invocar — incluindo as funções que implementam sua lógica personalizada (usadas para definir UDFs), bem como funções de suporte necessárias para o gerenciamento de memória e a troca de dados entre o ClickHouse e o código WebAssembly.

Seu código deve ser compilado para WebAssembly "freestanding" (também conhecido como `wasm32-unknown-unknown`), sem nenhuma dependência de sistema operacional ou biblioteca padrão. Além disso, apenas o alvo padrão de WebAssembly de 32 bits é compatível (sem a extensão `wasm64`).
O módulo deve seguir um dos protocolos de comunicação (ABIs) compatíveis para interagir com o ClickHouse.

Depois de compilado, o código binário do módulo é carregado no ClickHouse por meio da inserção na tabela `system.webassembly_modules`.
Depois disso, você pode criar UDFs que fazem referência a funções exportadas pelo módulo usando a instrução `CREATE FUNCTION ... LANGUAGE WASM`.

<div id="prerequisites">
  ## Pré-requisitos
</div>

Ative o suporte a WebAssembly na configuração do ClickHouse:

```xml theme={null}
<clickhouse>
    <allow_experimental_webassembly_udf>true</allow_experimental_webassembly_udf>
    <webassembly_udf_engine>wasmtime</webassembly_udf_engine>
</clickhouse>
```

Implementações de engine disponíveis:

* `wasmtime` (padrão, recomendado) — usa [WasmTime](https://github.com/bytecodealliance/wasmtime)
* `wasmedge` — usa [WasmEdge](https://github.com/WasmEdge/WasmEdge)

<div id="quick-start">
  ## Início rápido
</div>

Este exemplo demonstra o fluxo completo de criação de uma WebAssembly UDF, implementando uma calculadora da [conjectura de Collatz](https://en.wikipedia.org/wiki/Collatz_conjecture).

Vamos escrever o código no formato WebAssembly Text (WAT), que é uma representação legível do WebAssembly, então não é necessário usar nenhuma linguagem de programação nesta etapa.
O ClickHouse exige que o módulo esteja em formato binário, por isso usaremos um transpilador para converter WAT em WASM.
Para realizar essa conversão, você pode usar o `wat2wasm`, do [WebAssembly Binary Toolkit (WABT)](https://github.com/WebAssembly/wabt), ou o comando `parse`, do [wasm-tools](https://github.com/bytecodealliance/wasm-tools).

```bash theme={null}
cat << 'EOF' | wasm-tools parse | clickhouse client -q "INSERT INTO system.webassembly_modules (name, code) SELECT 'collatz', code FROM input('code String') FORMAT RawBlob"
(module
  (func $next (param $n i32) (result i32)
    local.get $n i32.const 1 i32.and
    (if (result i32)
      (then local.get $n i32.const 3 i32.mul i32.const 1 i32.add)
      (else local.get $n i32.const 2 i32.div_u)))
  (func $steps (export "steps") (param $n i32) (result i32)
    (local $count i32)
    local.get $n i32.const 1 i32.lt_u
    (if (then i32.const 0 return))
    (block $done (loop $loop
      local.get $n i32.const 1 i32.eq br_if $done
      local.get $n call $next local.set $n
      local.get $count i32.const 1 i32.add local.set $count
      br $loop))
    local.get $count)
)
EOF
```

No trecho acima, enviamos o código binário WASM diretamente para o ClickHouse client usando `FORMAT RawBlob` para inseri-lo na tabela `system.webassembly_modules`.

Em seguida, definimos a UDF que faz referência à função `steps` exportada pelo módulo:

```sql theme={null}
CREATE FUNCTION collatz_steps LANGUAGE WASM ARGUMENTS (n UInt32) RETURNS UInt32 FROM 'collatz' :: 'steps';
```

Observe que especificamos o nome da função no módulo após `::`, pois ele difere do nome da UDF.

Agora podemos usar a função `collatz_steps` em nossas consultas:

```sql theme={null}
SELECT groupArray(collatz_steps(number :: UInt32))
FROM numbers(1, 100)
FORMAT TSV
```

A coluna `number` é convertida explicitamente para `UInt32`, porque as funções WebAssembly exigem uma correspondência exata de tipos com a assinatura especificada na instrução `CREATE FUNCTION`.

No resultado, obtivemos a sequência de etapas de Collatz para números de 1 a 100, correspondente à sequência [A006577 da OEIS](https://oeis.org/A006577).

```text theme={null}
[0,1,7,2,5,8,16,3,19,6,14,9,9,17,17,4,12,20,20,7,7,15,15,10,23,10,111,18,18,18,106,5,26,13,13,21,21,21,34,8,109,8,29,16,16,16,104,11,24,24,24,11,11,112,112,19,32,19,32,19,19,107,107,6,27,27,27,14,14,14,102,22,115,22,14,22,22,35,35,9,22,110,110,9,9,30,30,17,30,17,92,17,17,105,105,12,118,25,25,25]
```

<div id="manage-wasm-modules-via-system-table">
  ## Gerencie módulos WASM por meio da tabela de sistema
</div>

Os módulos WebAssembly são armazenados na tabela `system.webassembly_modules`, que tem a seguinte estrutura:

* **Colunas**
  * `name` String — Nome do módulo. Não pode estar vazio; apenas caracteres de palavra.
  * `code` String — Código WASM binário bruto. Somente para escrita; as leituras retornam uma string vazia.
  * `hash` UInt256 — SHA256 do binário do módulo (zero se estiver presente em disco, mas ainda não tiver sido carregado).

O gerenciamento de módulos é feito por meio de operações SQL padrão nessa tabela:

<div id="insert-a-module">
  ### Inserir um módulo
</div>

```sql theme={null}
INSERT INTO system.webassembly_modules (name, code)
SELECT 'my_module', base64Decode('AGFzbQEAAAA...');
```

Opcionalmente, informe o hash de integridade:

```sql theme={null}
INSERT INTO system.webassembly_modules (name, code, hash)
SELECT 'my_module', base64Decode('...'), reinterpretAsUInt256(unhex('369f...c57d'));
```

Se o hash fornecido não corresponder ao SHA256 calculado para o código do módulo, a inserção falhará. Isso pode ser útil ao carregar módulos a partir de fontes externas, como S3 ou HTTP.

<div id="distribute-a-module-across-a-cluster">
  ### Distribuir um módulo em um cluster
</div>

`system.webassembly_modules` é uma tabela por instância — um `INSERT` é gravado apenas na réplica que atende à conexão. Não existe uma forma `ON CLUSTER` para a instrução `INSERT`, portanto, um `CREATE FUNCTION ... ON CLUSTER` subsequente falhará nas réplicas que não têm o módulo:

```text theme={null}
Code: 674. DB::Exception: WebAssembly module 'collatz' not found:
while adding user defined function `collatz_steps`. (RESOURCE_NOT_FOUND)
```

Para propagar um insert para todos os nós, grave na função de tabela `cluster` em vez de na tabela local `system.webassembly_modules`:

```bash theme={null}
cat collatz.wasm | clickhouse client -q "
  INSERT INTO FUNCTION cluster('default', 'system', 'webassembly_modules') (name, code)
  SELECT 'collatz', code FROM input('code String') FORMAT RawBlob"
```

<Note>
  Esse padrão depende de o caminho subjacente de gravação distribuída passar por cada réplica em cada shard, o que só acontece quando o cluster está configurado com `internal_replication=false`. Com `internal_replication=true` (o padrão para clusters que usam `ReplicatedMergeTree` para gerenciar a própria replicação), o insert é enviado para uma única réplica íntegra por shard, e `system.webassembly_modules` não é replicado por esse caminho — portanto, algumas réplicas ainda ficarão sem o módulo. Nessa configuração, você precisa fazer o insert em cada réplica individualmente, por exemplo iterando sobre `system.clusters` e gravando via `remote(...)` por host, ou copiando o binário para `user_scripts/wasm/` em cada host.

  Você pode verificar `internal_replication` de um cluster com `SELECT cluster, shard_num, internal_replication FROM system.clusters`.
</Note>

Após o insert distribuído, o módulo passa a estar presente em todas as réplicas e `CREATE FUNCTION ... ON CLUSTER` é executado com sucesso:

```sql theme={null}
CREATE FUNCTION collatz_steps ON CLUSTER 'default'
LANGUAGE WASM FROM 'collatz' :: 'steps'
ARGUMENTS (n UInt32) RETURNS UInt32;
```

Você pode verificar se o módulo está carregado em todo o cluster com `clusterAllReplicas`:

```sql theme={null}
SELECT hostName(), name FROM clusterAllReplicas('default', system.webassembly_modules) WHERE name = 'collatz';
```

As inserções em `system.webassembly_modules` são idempotentes para o mesmo par `(name, hash)`, portanto executar novamente a inserção distribuída é seguro e é uma forma razoável de reparar o estado depois que uma réplica for substituída. Observe que servidores adicionados recentemente não recebem módulos existentes retroativamente — você deve executar novamente a inserção no cluster atualizado ou colocar o binário no diretório `user_scripts/wasm/` no novo host.

<div id="list-modules">
  ### Listar módulos
</div>

```sql theme={null}
SELECT name, lower(hex(reinterpretAsFixedString(hash))) AS sha256 FROM system.webassembly_modules

   ┌─name────┬─sha256───────────────────────────────────────────────────────────┐
1. │ collatz │ a084a10b7b5cb07db198bc93bf1f3c1f8cb8ef279df7a4f6b66b1cdd55d79c48 │
   └─────────┴──────────────────────────────────────────────────────────────────┘
```

<div id="delete-a-module">
  ### Excluir um módulo
</div>

A exclusão é feita pela instrução `DELETE FROM system.webassembly_modules WHERE name = '...'`.
O predicado deve ser `name = 'literal'` para correspondência exata ou `name LIKE 'pattern'` para excluir todos os módulos cujo nome corresponda ao padrão; nenhum outro formato é aceito.

```sql theme={null}
DELETE FROM system.webassembly_modules WHERE name = 'collatz';

-- Exclusão em massa de todos os módulos cujo nome começa com `tmp_` (o sublinhado literal é escapado como `\_`):
DELETE FROM system.webassembly_modules WHERE name LIKE 'tmp\_%';
```

Se alguma UDF existente fizer referência a um dos módulos encontrados, a exclusão falhará; portanto, primeiro você deve excluir essas UDFs.

<div id="create-a-webassembly-udf">
  ## Criar uma UDF em WebAssembly
</div>

**Sintaxe**:

```sql theme={null}
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 | ABI ASSEMBLYSCRIPT]
[DETERMINISTIC]
[SHA256_HASH 'hex']
[SETTINGS key = value[, ...]];
```

**Parâmetros**:

* `function_name`: Nome da função no ClickHouse. Pode ser diferente do nome da função exportada no módulo.
* `FROM 'module_name' :: 'source_function_name'`: Nome do módulo WASM carregado e nome da função no módulo WASM a ser usada (o padrão é function\_name)
* `ARGUMENTS`: Lista de nomes e tipos de argumentos (os nomes são opcionais e usados em formatos de serialização compatíveis com campos nomeados)
* `ABI`: Versão da Interface Binária de Aplicação
  * `ROW_DIRECT`: Mapeamento direto de tipos, processamento linha por linha
  * `BUFFERED_V1`: Processamento baseado em blocos com serialização
  * `ASSEMBLYSCRIPT`: Processamento linha por linha para módulos produzidos pelo compilador [AssemblyScript](https://www.assemblyscript.org). Tipos numéricos são mapeados para tipos primitivos do AssemblyScript; `String` do ClickHouse é mapeado para `string` do AssemblyScript.
* `DETERMINISTIC`: Declara a função como determinística — sempre retorna a mesma saída para a mesma entrada. Quando especificado, o ClickHouse pode fazer o constant folding de chamadas em que todos os argumentos são constantes: a função é avaliada uma vez durante a análise da consulta, e o resultado é reutilizado para cada linha.
* `SHA256_HASH`: Hash esperado do módulo para verificação (preenchido automaticamente se omitido); pode ser usado para garantir que o módulo WASM correto seja carregado em diferentes réplicas.
* `SETTINGS`: Configurações por função
  * `serialization_format` String — Formato usado para serializar blocos de argumentos passados ao módulo e analisar o resultado retornado. Usado apenas por `ABI BUFFERED_V1`. Valores compatíveis: `MsgPack`, `JSONEachRow`, `CSV`, `TSV`, `TSVRaw`, `RowBinary` e `Buffers`. Padrão: `MsgPack`. Formatos baseados em blocos, como `Buffers`, devem retornar uma única coluna cujo tipo corresponda à assinatura da função declarada.
  * `webassembly_udf_enable_fuel` Bool — Habilita um orçamento finito de fuel para a função. Padrão: `true`. Quando `false`, a configuração no nível da consulta `webassembly_udf_max_fuel` é ignorada para esta função. Desabilitar os limites de fuel pode melhorar o desempenho ao usar o engine `wasmtime`. No entanto, para código guest não confiável ou com bugs, isso pode aumentar o risco de execução descontrolada.

<div id="abis-versions">
  ## Versões de ABI
</div>

Para interagir com o ClickHouse, os módulos WebAssembly devem seguir uma das ABIs (Application Binary Interfaces) compatíveis.

* `ROW_DIRECT`: Mapeamento direto de tipos (somente tipos primitivos `Int32`, `UInt32`, `Int64`, `UInt64`, `Float32`, `Float64`)
* `BUFFERED_V1`: Tipos complexos com serialização
* `ASSEMBLYSCRIPT`: Interoperação linha por linha com módulos [AssemblyScript](https://www.assemblyscript.org); oferece suporte a tipos numéricos e `String`.

<div id="abi-row_direct">
  ### ABI ROW\_DIRECT
</div>

Chama diretamente uma função WASM exportada para cada linha.

* Argumentos e tipos de retorno devem ser tipos numéricos `Int32/UInt32/Int64/UInt64/Float32/Float64/Int128/UInt128`.
* Strings não são compatíveis com esta ABI.
* As assinaturas devem corresponder à exportação WASM (`i32/i64/f32/f64/v128`).
* O módulo não precisa exportar funções de suporte.

Por exemplo, uma função com a assinatura:

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

Pode ser criado da seguinte forma:

```sql theme={null}
CREATE FUNCTION my_func ARGUMENTS (Int32, UInt64, Float32) RETURNS Float64 ...
```

O WebAssembly não faz distinção entre argumentos com sinal e sem sinal; em vez disso, usa instruções diferentes para interpretar os valores. Assim, o tamanho do argumento deve corresponder exatamente, enquanto o uso de sinal é determinado pelas operações dentro da função.

<div id="abi-buffered_v1">
  ### ABI BUFFERED\_V1
</div>

<Note>
  Esta ABI é experimental e está sujeita a alterações em lançamentos futuros.
</Note>

Processa blocos inteiros de uma só vez usando (des)serialização por meio da memória WASM. Compatível com quaisquer tipos de argumentos e de retorno.

Os dados são trocados por meio de buffers na memória WASM. Um buffer é uma estrutura de 8 bytes que contém um ponteiro para os dados e o tamanho deles (dois valores `u32` little-endian). Os buffers são passados por identificador — um ponteiro para essa estrutura, e não para os próprios dados. O código guest deve exportar duas funções para criar e destruir esses buffers.

Para cada bloco de entrada, o ClickHouse:

1. Serializa as colunas de argumentos usando o `serialization_format` da função (`MsgPack` por padrão). Formatos baseados em linhas gravam os valores linha a linha, com os valores dos argumentos na ordem em que são declarados em `ARGUMENTS`; formatos com campos nomeados usam os nomes dos argumentos, portanto, declare-os em `ARGUMENTS` ao usar esses formatos.
2. Chama `clickhouse_create_buffer`, exportada pelo módulo, e copia os dados serializados para a memória apontada pelo buffer retornado.
3. Chama a função definida pelo usuário com dois argumentos `i32`: o identificador do buffer de entrada (`0` se a função não tiver argumentos) e o número de linhas. A função retorna um único `i32` — o identificador do buffer de resultado, que o próprio código guest aloca; retornar `0` faz a consulta falhar com um erro.
4. Lê o buffer de resultado: ele deve conter exatamente uma coluna com exatamente o mesmo número de linhas, serializada no mesmo formato. Para formatos com campos nomeados, como `JSONEachRow`, a coluna de resultado deve se chamar `result`.
5. Chama `clickhouse_destroy_buffer` nos identificadores dos buffers de entrada (se houver) e de resultado. O código guest não deve liberar o buffer de resultado por conta própria nem retornar o identificador de entrada como resultado — caso contrário, ele seria destruído duas vezes.

A função é invocada uma vez por bloco de entrada: uma consulta grande é dividida em vários blocos pelo pipeline de consulta (o número máximo de linhas por chamada também pode ser limitado pela configuração `webassembly_udf_max_input_block_size`). Portanto, a contagem de linhas passada em cada chamada corresponde ao tamanho desse bloco, e não ao da consulta inteira.

<Note>
  Os bytes exatos dentro dos buffers são definidos pelo formato escolhido, e o código guest deve decodificá-los e codificá-los por conta própria. Em particular, para valores `String`:

  * `MsgPack`: o ClickHouse grava valores `String` usando a família de tipos `bin` (`0xc4`/`0xc5`/`0xc6`), e não a família `str`. Ambas as famílias são aceitas durante a conversão do resultado.
  * `RowBinary`: cada `String` é prefixada com seu comprimento em bytes como um varint sem sinal ([LEB128](https://en.wikipedia.org/wiki/LEB128)), e não como um inteiro de largura fixa.
  * `JSONEachRow`: cada linha de resultado deve ser um objeto com a chave `result`, por exemplo, `{"result":"value"}`.
</Note>

```
(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
)
```

Um exemplo completo em C freestanding: `str_reverse` inverte os bytes de cada string de entrada usando `serialization_format = 'RowBinary'`. As instâncias do módulo são reutilizadas entre blocos, portanto `clickhouse_destroy_buffer` precisa realmente liberar a memória — aqui, o allocator é redefinido quando todos os buffers são destruídos.

```c theme={null}
#include <stdint.h>

typedef struct {
    uint8_t * data;
    uint32_t size;
} ClickHouseBuffer;

#define HEAP_SIZE (1 << 24)
static _Alignas(16) uint8_t heap[HEAP_SIZE];
static uint32_t heap_pos = 0;
static uint32_t live_buffers = 0;

__attribute__((export_name("clickhouse_create_buffer")))
ClickHouseBuffer * clickhouse_create_buffer(uint32_t size)
{
    uint32_t total = (sizeof(ClickHouseBuffer) + size + 15u) & ~15u;
    if (heap_pos + total > HEAP_SIZE)
        return 0; /* a zero handle makes the host fail the query with an error */
    ClickHouseBuffer * buf = (ClickHouseBuffer *) &heap[heap_pos];
    buf->data = &heap[heap_pos + sizeof(ClickHouseBuffer)];
    buf->size = size;
    heap_pos += total;
    ++live_buffers;
    return buf;
}

__attribute__((export_name("clickhouse_destroy_buffer")))
void clickhouse_destroy_buffer(ClickHouseBuffer * buf)
{
    if (--live_buffers == 0)
        heap_pos = 0;
}

/* RowBinary prefixes each String with its byte length as an unsigned varint (LEB128) */
static uint64_t read_varint(const uint8_t ** pp)
{
    uint64_t value = 0;
    for (int shift = 0;; shift += 7)
    {
        uint8_t b = *(*pp)++;
        value |= (uint64_t)(b & 0x7f) << shift;
        if (!(b & 0x80))
            return value;
    }
}

static void write_varint(uint8_t ** pp, uint64_t value)
{
    while (value >= 0x80)
    {
        *(*pp)++ = (uint8_t)(value | 0x80);
        value >>= 7;
    }
    *(*pp)++ = (uint8_t)value;
}

/* Reverses the bytes of each input string */
__attribute__((export_name("str_reverse")))
ClickHouseBuffer * str_reverse(ClickHouseBuffer * input, uint32_t num_rows)
{
    ClickHouseBuffer * out = clickhouse_create_buffer(input->size);
    if (!out)
        return 0;
    const uint8_t * in = input->data;
    uint8_t * o = out->data;
    for (uint32_t row = 0; row < num_rows; ++row)
    {
        uint64_t len = read_varint(&in);
        write_varint(&o, len);
        for (uint64_t i = 0; i < len; ++i)
            o[i] = in[len - 1 - i];
        in += len;
        o += len;
    }
    out->size = (uint32_t)(o - out->data);
    return out;
}
```

Compile usando clang e `wasm-ld` (incluídos no LLVM/lld):

```bash theme={null}
clang --target=wasm32 -ffreestanding -nostdlib -fno-builtin -c str_reverse.c
wasm-ld --no-entry str_reverse.o -o str_reverse.wasm
```

As funções devem estar visíveis nas exportações do módulo: marque-as com `__attribute__((export_name("...")))`, como acima, ou faça a vinculação com `wasm-ld --export-all`. `-fno-builtin` impede que o clang converta loops simples de bytes em chamadas a `memcpy`/`memset`, que não estão disponíveis sem uma biblioteca padrão.

Carregue o módulo e crie a função:

```bash theme={null}
cat str_reverse.wasm | clickhouse client -q "INSERT INTO system.webassembly_modules (name, code) SELECT 'str_reverse', code FROM input('code String') FORMAT RawBlob"
```

```sql theme={null}
CREATE FUNCTION str_reverse LANGUAGE WASM ABI BUFFERED_V1
FROM 'str_reverse' :: 'str_reverse'
ARGUMENTS (s String) RETURNS String
SETTINGS serialization_format = 'RowBinary';

SELECT str_reverse(toString(number + 100)) FROM numbers(3);
```

```text theme={null}
001
101
201
```

<div id="abi-assemblyscript">
  ### ABI ASSEMBLYSCRIPT
</div>

Destina-se a módulos produzidos pelo compilador [AssemblyScript](https://www.assemblyscript.org). Cada linha aciona uma chamada para a função exportada, mapeando valores do ClickHouse para tipos primitivos do AssemblyScript e objetos string.

**Tipos compatíveis**:

* Numéricos: `Int8`/`UInt8`, `Int16`/`UInt16` (ampliados para `i32` no limite), `Int32`/`UInt32`, `Int64`/`UInt64`, `Float32`, `Float64`

* `String` — corresponde a `string` do AssemblyScript (UTF-16 na memória WASM). O ClickHouse lida automaticamente com a conversão UTF-8 ↔ UTF-16.

* Classes personalizadas do AssemblyScript não são compatíveis como tipos de argumento ou de retorno — seus IDs de classe do runtime não são estáveis entre compilações (consulte [AssemblyScript#2982](https://github.com/AssemblyScript/assemblyscript/issues/2982)).

**Requisitos do módulo**:

O módulo deve ser compilado com o runtime gerenciado do AssemblyScript para que `__new`, `__pin` e `__unpin` sejam exportados. O tratamento padrão de strings de entrada e saída pressupõe isso. A invocação recomendada:

```bash theme={null}
asc src.ts --runtime incremental --exportRuntime -o src.wasm
```

O AssemblyScript também importa `env.abort` para traps de runtime (falta de memória, verificações de limites etc.). O ClickHouse fornece essa importação automaticamente: quando um `abort` é disparado, a consulta ativa falha com uma exceção `WASM_ERROR` que inclui a mensagem decodificada do AssemblyScript e o local no código-fonte.

**Exemplo**:

```typescript theme={null}
// src.ts
export function add(a: u32, b: u32): u32 {
  return a + b;
}

export function greet(name: string): string {
  return "Hello, " + name + "!";
}
```

Após compilar com `asc` e carregar o `.wasm` resultante em `system.webassembly_modules`, declare as UDFs da seguinte forma:

```sql theme={null}
CREATE FUNCTION as_add
    LANGUAGE WASM ABI ASSEMBLYSCRIPT
    FROM 'as_example' :: 'add'
    ARGUMENTS (a UInt32, b UInt32) RETURNS UInt32;

CREATE FUNCTION as_greet
    LANGUAGE WASM ABI ASSEMBLYSCRIPT
    FROM 'as_example' :: 'greet'
    ARGUMENTS (name String) RETURNS String;
```

<div id="note-for-developing-udfs-in-rust">
  ### Observação sobre o desenvolvimento de UDFs em Rust
</div>

Para programas em Rust, fornecemos um crate auxiliar [clickhouse-wasm-udf](https://crates.io/crates/clickhouse-wasm-udf) para simplificar o desenvolvimento de WebAssembly UDFs para o ClickHouse. O crate fornece funções para gerenciamento de memória, então você não precisa implementar manualmente as funções `clickhouse_create_buffer` e `clickhouse_destroy_buffer`; basta adicionar o crate como dependência. Também há macros `#[clickhouse_wasm_udf]` para encapsular suas funções Rust comuns no formato ABI exigido.

Com o crate, você pode escrever UDFs assim:

```rust theme={null}

use clickhouse_wasm_udf_bindgen::clickhouse_udf;

#[clickhouse_udf]
pub fn some_udf(data: String) -> HashMap<String, String> {
    // Sua implementação aqui
}

```

Macros geram uma função wrapper que aceita e retorna estruturas de buffer e lida automaticamente com a serialização/desserialização usando `serde`.

<div id="host-api-available-to-modules">
  ## API do host disponível para módulos
</div>

As funções de host a seguir podem ser importadas e usadas por módulos:

* `clickhouse_server_version() -> i64` — retorna a versão do ClickHouse server como um inteiro (por exemplo, 25011001 para v25.11.1.1).
* `clickhouse_throw(ptr: i32, size: i32)` — gera um erro com a mensagem fornecida. Aceita um ponteiro para a posição de memória que contém a string da mensagem de erro e o tamanho da string.
* `clickhouse_log(ptr: i32, size: i32)` — registra uma mensagem no log de texto do ClickHouse server.
* `clickhouse_random(ptr: i32, size: i32)` — preenche a memória com bytes aleatórios.
* `env.abort(message: i32, fileName: i32, line: i32, column: i32)` — fornecido para módulos compatíveis com AssemblyScript. Chamá-lo (ou disparar uma trap de runtime do AssemblyScript que o chame) encerra a UDF com uma exceção `WASM_ERROR` contendo a mensagem decodificada e a localização no código-fonte. Módulos que não importam `env.abort` não são afetados.

<div id="settings">
  ## Configurações
</div>

As configurações a seguir, no nível da consulta, controlam a execução de UDFs em WebAssembly:

* `webassembly_udf_max_fuel` — Limite de fuel por execução de uma instância de UDF em WebAssembly. Cada instrução de WebAssembly consome uma certa quantidade de fuel. O valor é escalado por 1024 antes de ser passado ao runtime, portanto `webassembly_udf_max_fuel = 1` corresponde a aproximadamente 1024 unidades de fuel. Defina como 0 para não haver limite finito. Aplica-se apenas a funções cuja configuração por função `webassembly_udf_enable_fuel` seja `true`, que é o padrão.

* `webassembly_udf_max_memory` — Limite de memória, em bytes, por instância de UDF em WebAssembly.

* `webassembly_udf_max_input_block_size` — Número máximo de linhas passadas para uma UDF em WebAssembly em um único bloco. Defina como 0 para processar todas as linhas de uma só vez.

* `webassembly_udf_max_instances` — Número máximo de instâncias de UDF em WebAssembly que podem ser executadas em paralelo por função.

Exemplo de uso:

```sql theme={null}
SET webassembly_udf_max_fuel = 200000;
SELECT my_wasm_udf(column) FROM table;
```

<div id="see-also">
  ## Veja também
</div>

* [Visão geral das UDFs do ClickHouse](/pt-BR/reference/functions/regular-functions/udf)
