Funções Definidas pelo Usuário (UDF) permitem que os usuários ampliem o comportamento do ClickHouse para além do que é oferecido por mais de mil funções nativas.
No ClickHouse Cloud, há várias maneiras de criar e gerenciar funções definidas pelo usuário:
- Usando SQL
- Usando a UI e seu próprio código (beta pública)
- Usando a Cloud API (beta)
- Usando o Terraform (beta)
Funções Definidas pelo Usuário em SQL
As UDFs em SQL podem ser criadas usando a instrução CREATE FUNCTION a partir de uma expressão lambda.
Neste exemplo, vamos criar uma função definida pelo usuário executável simples, isBusinessHours.
A função verificará se um determinado timestamp está dentro do horário comercial e retornará true se estiver; caso contrário, false.
- Faça login no Cloud Console e abra o SQL Console
- Escreva a seguinte consulta SQL para criar a função
isBusinessHours:
CREATE FUNCTION isBusinessHours AS (ts) ->
toDayOfWeek(ts) BETWEEN 1 AND 5
AND toHour(ts) BETWEEN 9 AND 17;- Execute o comando abaixo para testar sua UDF recém-criada:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);Você deverá receber o seguinte resultado:
1 0- Você pode usar o comando
DROP FUNCTIONpara remover a UDF que acabou de criar:
DROP FUNCTION isBusinessHoursIsso significa:
- As configurações no nível da sessão (definidas pela instrução
SET) não são propagadas para o contexto de execução das UDFs - As configurações de perfil do usuário não são herdadas pelas UDFs
- As configurações no nível da consulta não se aplicam durante a execução das UDFs
Funções Definidas pelo Usuário criadas via UI
O ClickHouse Cloud oferece uma interface na UI para criar funções definidas pelo usuário.
Neste exemplo, vamos criar a mesma função definida pelo usuário executável simples, isBusinessHours, que verifica se um determinado timestamp está dentro do horário comercial.
Anteriormente, nós a criamos usando SQL, mas desta vez vamos criá-la em Python e configurá-la pela UI.
Crie o arquivo Python
Crie localmente um novo arquivo main.py:
cat > main.py << 'EOF'
import sys
from datetime import datetime
for line in sys.stdin:
ts = datetime.fromisoformat(line.strip())
result = 1 if (0 <= ts.weekday() <= 4 and 9 <= ts.hour <= 17) else 0
print(result)
sys.stdout.flush()
EOFSe o seu script em Python importar pacotes de terceiros, liste-os em um arquivo requirements.txt, e o ClickHouse Cloud os instalará para você. Como alternativa, você pode empacotar as dependências diretamente no ZIP, mas, nesse caso, deverá incluir os pacotes em cache para ambas as arquiteturas de CPU, portanto o requirements.txt é mais simples. Por exemplo:
requests>=2.28.0
numpy>=1.23.0Empacote as dependências e os arquivos locais
Para incluir pacotes de dependência e quaisquer arquivos locais adicionais (como arquivos wheel, arquivos de configuração ou arquivos de dados), coloque-os no mesmo diretório que main.py e requirements.txt. Ao criar o arquivo ZIP, inclua todos os arquivos:
zip is_business_hours.zip main.py requirements.txtVocê pode fazer referência ao diretório base do caminho local incluído no pacote no seu código Python usando os.path.dirname(os.path.abspath(__file__)). Isso retorna o caminho absoluto para o diretório em que o main.py está localizado dentro do arquivo ZIP, permitindo acessar outros arquivos incluídos no pacote:
import os
# Get the base directory of the bundled files
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(base_dir, 'config.json')Isso é útil quando você precisa:
- Acessar arquivos de configuração incluídos na sua UDF
- Carregar pacotes wheel para dependências personalizadas
- Referenciar scripts adicionais ou arquivos de dados
Agora compacte o arquivo em um arquivo ZIP:
zip is_business_hours.zip main.pyCriar uma UDF pela UI
- Na página inicial do Cloud Console, clique no nome da sua organização no menu no canto inferior esquerdo.
- Selecione Funções Definidas pelo Usuário no menu.
- Na página de funções definidas pelo usuário, clique em Set up a UDF. Um painel de configuração é aberto no lado direito da tela.
- Digite um nome para a função. Para este exemplo, use
isBusinessHours. - Selecione um tipo de função: Executable pool ou Executable:
- Executable pool: Um pool de processos persistentes é mantido, e um processo é obtido desse pool para leituras.
- Executable: O script é executado em cada consulta.
- Para este exemplo, use as configurações padrão. Para ver a lista completa dos parâmetros de configuração, consulte Funções definidas pelo usuário executáveis.
- Clique em Browse File para fazer upload do arquivo
.zipcriado no início deste tutorial. - Adicione um novo argumento. Para este exemplo, adicione o argumento
timestampcom o tipoDateTime. - Selecione um tipo de retorno. Para este exemplo, selecione
Bool. - Clique em Create UDF. Uma caixa de diálogo exibe o status atual da compilação.
- Se houver algum problema, o status muda para error.
- Caso contrário, o status avança de building para provisioning. Seu serviço precisa estar ativo para concluir o provisioning. Se o serviço estiver ocioso, clique em Wake Up Service no painel UDF details, ao lado do nome do serviço.
- Quando a implantação for concluída, o status muda para deployed.
Teste sua UDF
- volte à página inicial do SQL Console clicando em Settings - voltar para a visão do seu serviço no canto superior esquerdo da página
- clique em SQL Console no menu à esquerda
- escreva a seguinte consulta:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);Você deverá ver o seguinte resultado:
true falseCriar uma nova versão
Para alterar o código de uma UDF, crie uma nova versão. O painel Edit gerencia apenas a quais serviços uma UDF está atribuída; fazer upload de um arquivo ali não substituirá o código implantado.
- Na página inicial do Cloud Console, clique no nome da sua organização no menu no canto inferior esquerdo.
- Selecione Funções Definidas pelo Usuário no menu.
- Clique nos três pontos em Ações da UDF
isBusinessHourse, em seguida, em Criar nova versão - Faça upload de um arquivo zip com o código modificado ou altere as configurações e clique em Criar nova versão
Você adicionou com sucesso sua primeira função definida pelo usuário pela UI, confirmou que ela é executada e viu como criar uma nova versão, se necessário.
Gerencie UDFs com a Cloud API
Tudo o que está disponível na UI também pode ser acessado programaticamente por meio da ClickHouse Cloud API. Os endpoints de UDF permitem automatizar todo o ciclo de vida de uma UDF: fazer upload de arquivos de origem, criar funções e versões, anexá-las a serviços e removê-las.
O fluxo de trabalho típico para criar e implantar uma UDF pela API é:
- Crie uma URL de upload para obter uma URL pré-assinada para upload de
application/zipe, em seguida, faça upload do seu arquivo ZIP. Cada ID de upload pode ser usado em apenas uma tentativa de criação ou versionamento; solicite uma nova URL de upload ao tentar novamente. - Crie a UDF a partir do arquivo enviado, especificando o nome da função, o runtime, os argumentos e o tipo de retorno.
- Anexe a UDF a um serviço. Quando a versão é omitida, a versão pronta mais recente é anexada. O serviço deve estar em execução; serviços inativos podem ser ativados antes.
O conjunto completo de endpoints:
| Endpoint | Descrição |
|---|---|
| Criar URL de upload de UDF | Cria uma URL pré-assinada para upload de application/zip com escopo de organização |
| Criar UDF | Cria uma nova UDF a partir de um arquivo enviado |
| Listar UDFs | Retorna a versão mais recente de cada UDF na organização |
| Obter UDF | Retorna a versão mais recente de uma UDF |
| Excluir UDF | Exclui todas as versões de uma UDF e a desanexa de todos os serviços |
| Criar versão de UDF | Usa um arquivo de origem, atribui uma versão e inicia a compilação da UDF |
| Listar versões de UDF | Retorna todas as versões de uma UDF |
| Excluir versão de UDF | Exclui uma versão de UDF que não está anexada a nenhum serviço |
| Anexar UDF ao serviço | Anexa uma versão de UDF a um serviço, substituindo a versão atual quando necessário |
| Listar anexos de UDF | Retorna os anexos atuais de uma UDF a serviços |
| Obter anexo de UDF | Retorna o anexo atual de uma UDF a um serviço |
| Desanexar UDF do serviço | Desanexa uma UDF de um serviço |
Consulte a referência da API de UDF para ver os schemas de solicitação e resposta.
Gerencie UDFs com o Terraform
O provider Terraform oficial do ClickHouse inclui dois recursos para gerenciar UDFs como infraestrutura como código:
clickhouse_udfgerencia a própria função. Ele aceita um arquivo ZIP com o código-fonte da função e publica uma nova versão sempre que o hash do arquivo é alterado, aguardando a conclusão da compilação.clickhouse_udf_attachmentanexa uma versão de UDF a um serviço. Um serviço comporta no máximo uma versão de uma função por vez. Você pode fixar um número de versão específico ou fazer referência aclickhouse_udf.<name>.versionpara atualizar automaticamente os serviços para a versão mais recente.
Por exemplo, para implantar com o Terraform a UDF isBusinessHours do exemplo anterior:
resource "clickhouse_udf" "is_business_hours" {
function_name = "isBusinessHours"
runtime = "python3.11"
type = "executable_pool"
return_type = "Bool"
arguments = [
{ name = "timestamp", type = "DateTime" },
]
source_archive_path = "${path.module}/is_business_hours.zip"
source_archive_hash = filebase64sha256("${path.module}/is_business_hours.zip")
}
resource "clickhouse_udf_attachment" "production" {
function_name = clickhouse_udf.is_business_hours.function_name
service_id = var.service_id
version = clickhouse_udf.is_business_hours.version
}A anexação só é concluída para versões prontas e pode levar vários minutos; serviços inativos são ativados automaticamente. A exclusão de um recurso clickhouse_udf remove todas as versões da função e a desanexa de todos os serviços.