Visão geral
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.
Pré-requisitos
Início rápido
wat2wasm, do WebAssembly Binary Toolkit (WABT), ou o comando parse, do wasm-tools.
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:
::, pois ele difere do nome da UDF.
Agora podemos usar a função collatz_steps em nossas consultas:
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.
Gerencie módulos WASM por meio da tabela de sistema
system.webassembly_modules, que tem a seguinte estrutura:
- Colunas
nameString — Nome do módulo. Não pode estar vazio; apenas caracteres de palavra.codeString — Código WASM binário bruto. Somente para escrita; as leituras retornam uma string vazia.hashUInt256 — SHA256 do binário do módulo (zero se estiver presente em disco, mas ainda não tiver sido carregado).
Inserir um módulo
Listar módulos
Excluir um módulo
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.
Criar uma UDF em WebAssembly
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çãoROW_DIRECT: Mapeamento direto de tipos, processamento linha por linhaBUFFERED_V1: Processamento baseado em blocos com serialização
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çãoserialization_formatString — Formato de serialização para a ABI, caso ela exija. Padrão:MsgPack.
Versões de ABI
ROW_DIRECT: Mapeamento direto de tipos (somente tipos primitivosInt32,UInt32,Int64,UInt64,Float32,Float64)BUFFERED_V1: Tipos complexos com serialização
ABI ROW_DIRECT
- 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.
ABI BUFFERED_V1
Esta ABI é experimental e pode mudar em versões futuras.
i32 e retorna um único valor i32.
O código guest processa os dados e retorna um ponteiro para o buffer de resultado com os dados serializados do resultado.
O código guest deve fornecer duas funções para criar e destruir esses buffers.
Observação sobre o desenvolvimento de UDFs em Rust
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:
serde.
API do host disponível para 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.
Configurações
-
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. Defina como 0 para não haver limite. -
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.