Skip to main content
Esta página é uma referência para autores de extensões em C++. Para o tutorial passo a passo, consulte Criando Extensões em C++. Para tipos de coluna personalizados, consulte Tipos Personalizados em C++.
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 via make_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.
Comunique sucesso, NULL, aviso ou erro chamando um método terminal no tipo de resultado: 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.
3. Para resultados de string, escreva em out.buffer() e chame out.set_length(n). Verifique out.buffer().size() antes de escrever.
  • out.buffer() retorna um Span<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.
4. Passe as mensagens de erro para out.error(msg). A mensagem é truncada em VEF_MAX_ERROR_LEN (512 bytes) se necessário. 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 via is_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/personalizado) ou out.set_length(n) após escrever em out.buffer() (string)
  • Retornar aviso: out.warning(msg) — retorna NULL para esta linha, adiciona um aviso SQL, continua a execução; no modo estrito, o MySQL promove isso a um erro em INSERT/UPDATE. Chame em vez de out.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:
Para detalhes dos métodos de PrerunArgs e PostrunArgs, consulte Estado por Instrução no guia de Desenvolvimento.
A maioria das extensões não precisa de hooks prerun/postrun. O SDK C++ trata automaticamente casos comuns, como verificação de tipos e dimensionamento do buffer de resultado; tanto para VDFs que retornam STRING quanto para as que retornam 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 prontas para uso. 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 com make_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 Aggregate VDFs para a API do builder e as assinaturas de callback. Operações de agregação integradas com tipos personalizados:
As funções de extensão são chamadas em um modelo de execução por linha:
  • Cada chamada de função processa uma linha com seu próprio buffer de resultado (thread-safe)
  • prerun/postrun fornecem 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
Boa prática: Projete funções para serem stateless, visando simplicidade e segurança.

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) sob villagesql/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:
Nenhum desses headers é incluído por <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.
Os headers Preview não são estáveis. Uma extensão compilada com eles pode quebrar quando o servidor for atualizado. Quando um recurso se estabiliza, seus headers são movidos para um caminho versionado do SDK C++ estável.

Gatilhos

Gatilhos disparam em tabelas com colunas de tipo personalizado. O corpo do gatilho pode referenciar colunas de tipo não personalizado de NEW e OLD. Acessar valores de coluna de tipo personalizado dentro do corpo de um gatilho ainda não tem suporte.