Curioso sobre por que a API tem essa aparência? Leia Happy Path, Escape Hatch,
and the Space Between para conhecer a
filosofia de design por trás da API tipada de argumento/resultado e dos hooks de nível mais baixo, como
prerun() e varargs.Contratos das Funções VDF
Estes contratos regem como as funções de implementação de VDF interagem com o runtime do VEF. Toda função registrada viamake_func<> deve segui-los.
Os tipos referenciados abaixo estão disponíveis via #include <villagesql/vsql.h>.
1. As funções de implementação de VDF são void e nunca retornam um valor.
out.set(...) / out.set_length(n), out.set_null(),
out.warning(msg) ou out.error(msg).
2. Verifique input.is_null() antes de chamar input.value().
Se is_null() retornar true, chamar value() é comportamento indefinido.
out.buffer() e chame out.set_length(n). Verifique out.buffer().size() antes de escrever.
out.buffer()retorna umSpan<char>sobre o buffer gerenciado pelo servidor.out.set_length(n)registra quantos bytes foram escritos.out.buffer().size()é a capacidade máxima. Sempre verifique antes de escrever.
out.error(msg). A mensagem é truncada para caber em VEF_MAX_ERROR_LEN (512 bytes, incluindo o NUL de terminação), e o servidor pode encurtá-la ainda mais.
out.error(msg) aceita um std::string_view. Ele copia a mensagem para um
buffer gerenciado pelo servidor e define o estado do resultado como erro em uma única chamada.
Implementar Funções
As funções de implementação usam tipos de argumento e resultado tipados:Tratando Valores NULL
Verifique se há NULL viais_null() e retorne NULL chamando set_null().
Opções de tratamento de NULL:
- Verificação de NULL na entrada:
input.is_null() - Retornar NULL:
out.set_null() - Retornar valor:
out.set(v)(numérico) ouout.set_length(n)após escrever emout.buffer()(string/personalizado) - Retornar aviso:
out.warning(msg)— retorna NULL para esta linha, adiciona um aviso SQL, continua a execução. No modo estrito, inserir o NULL resultante em uma coluna NOT NULL ainda falha com a rejeição de NULL comum do modo estrito (ERROR 1048 (23000): Column '<col>' cannot be null) — o aviso em si não se torna um erro, e uma coluna que aceita NULL recebe o NULL. Chame em vez deout.set(), não além dele. - Retornar erro:
out.error(msg)— aborta a execução da instrução
Tratamento de Erros
Retorne erros com mensagens personalizadas para falhas de validação ou entrada inválida:Estado por Instrução com Prerun/Postrun
Registre hooks com.prerun<>() e .postrun<>(). As assinaturas obrigatórias são:
PrerunArgs e PostrunArgs, consulte
Estado por Instrução
no guia de Desenvolvimento.
A maioria das extensões não precisa de hooks prerun/postrun. A verificação de tipos e o dimensionamento do buffer
de resultado são automáticos. Uma VDF que retorna STRING começa com um buffer de resultado de 1024 bytes;
quando ela escreve o que cabe e informa o comprimento total com
out.set_length(n), o
servidor aumenta o buffer e chama a VDF novamente. Para uma VDF que retorna CUSTOM, o
buffer de resultado é aumentado para acomodar o tipo de retorno resolvido antes de o corpo da VDF ser executado.
Use prerun/postrun somente quando
você precisar de uma configuração cara por instrução (como abrir conexões) que
não deveria acontecer por linha.Se você perceber que precisa de prerun/postrun para o seu caso de uso, compartilhe seu cenário no
Discord do VillageSQL, pois a equipe pode conseguir
adicionar suporte no SDK C++ para tratá-lo automaticamente.Funções de Agregação
As agregações integradas COUNT(DISTINCT), MIN, MAX e GROUP_CONCAT funcionam com tipos personalizados sem configuração adicional. MIN e MAX exigem uma função de comparação registrada no tipo. VDFs de agregação personalizadas também têm suporte. Registre uma commake_aggregate_func<State, &result_fn>("name"), depois encadeie .returns(),
.param(), .clear<>() e .accumulate<>() antes de chamar .build().
Tanto .clear<>() quanto .accumulate<>() são obrigatórios. Consulte
VDFs Agregadas para a
API do builder e as assinaturas de callback.
Operações de agregação integradas com tipos personalizados:
- Cada chamada de função processa uma linha com seu próprio buffer de resultado (thread-safe)
prerun/postrunfornecem configuração/finalização por instrução- Evite estado global: use parâmetros de função e valores de retorno em vez disso
- Se você tiver que usar estado global, proteja-o com mutexes/locks
Funções de Janela
As seguintes funções de janela funcionam com tipos personalizados:Tabelas Temporárias
Tipos personalizados funcionam em tabelas temporárias.CREATE TEMPORARY TABLE, INSERT
e ALTER TABLE se comportam da mesma forma que em tabelas permanentes.
APIs de Preview
Algumas capabilities do VEF estão disponíveis como headers opcionais (opt-in) sobvillagesql/preview/ na árvore de includes do SDK C++. A ABI e a API ainda estão
em desenvolvimento ativo e podem mudar sem aviso prévio.
Para optar por elas, adicione o include ao código-fonte da sua extensão. Por exemplo:
<villagesql/vsql.h>; você deve incluí-lo
diretamente ao optar por eles.
O layout de namespace sob vsql::preview é por capability, não havendo um único
padrão universal. A API do keyring usa vsql::preview_keyring::KeyringCapability;
a API do thread worker usa vsql::preview_thread_worker::ThreadWorkerCapability;
a API de consulta SQL usa vsql::preview_sql_query::SqlQueryCapability e deve ser
aberta a partir de um handle de thread de worker em segundo plano (vef_thread_handle_t *).
Verifique cada header para saber o namespace exato e o nome de classe que ele define.
Para a documentação completa da API Preview, consulte Capabilities Preview.
Gatilhos
Gatilhos disparam em tabelas com colunas de tipo personalizado. O corpo do gatilho pode referenciar colunas de tipo não personalizado deNEW e OLD. Acessar valores de
coluna de tipo personalizado dentro do corpo de um gatilho tem suporte: NEW.<column> e
OLD.<column> podem ser lidos diretamente e passados para funções de extensão.

