Skip to main content
Entender a arquitetura de extensões do VillageSQL ajuda a depurar problemas e otimizar o desempenho ao criar extensões. A jornada do autor de extensões é direta: você escreve funções em C++ ou Rust usando o SDK correspondente, compila-as em uma biblioteca compartilhada e empacota essa biblioteca junto com um manifesto em um arquivo .veb. Quando você executa INSTALL EXTENSION, o VillageSQL carrega sua biblioteca, chama seu código de registro e disponibiliza suas funções imediatamente como SQL, chamáveis a partir de qualquer consulta como se estivessem integradas ao servidor. Nenhuma reinicialização do servidor é necessária. O restante desta página explica como cada etapa desse processo funciona.

Terminologia

  • VEB (VillageSQL Extension Bundle) - O formato de arquivo .veb, um arquivo tar contendo manifesto, biblioteca e metadados
  • VEF (VillageSQL Extension Framework) - Os SDKs de C++ e Rust para criação de extensões
  • VDF (VillageSQL Defined Function) - Funções registradas por meio do VEF, via VEF_GENERATE_ENTRY_POINTS() em C++ ou a macro extension! em Rust

Busca de Funções VDF

As VDFs oferecem suporte a chamadas de função qualificadas e não qualificadas:
Ordem de resolução:
  1. Funções do sistema (integradas ao MySQL)
  2. UDFs (funções tradicionais definidas pelo usuário do MySQL via CREATE FUNCTION ... SONAME)
  3. VDFs (funções de extensão) - somente se existir exatamente uma função com esse nome
  4. Funções armazenadas (criadas com CREATE FUNCTION)
Se mais de uma extensão registrar uma função com o mesmo nome, a chamada não qualificada é ambígua e o nome totalmente qualificado (extension_name.function_name()) deve ser usado. Desempenho: Para caminhos de código intensivos, use chamadas qualificadas (extension_name.function_name()) para pular a cadeia de resolução e invocar diretamente a função de extensão.

Formato de Arquivo VEB

As extensões do VillageSQL são distribuídas como arquivos .veb (VillageSQL Extension Bundle) - arquivos tar contendo:

Esquema do manifest.json

  • name: Deve corresponder ao nome da extensão usado em SQL (lowercase_with_underscores)
  • version: Versão semântica (MAJOR.MINOR.PATCH)
  • description, author, license: Metadados opcionais

Ciclo de Vida da Extensão

Fluxo de Instalação

Reversão: Se qualquer etapa falhar, todas as alterações são desfeitas e a .so é descarregada. Isolamento de Símbolos: As extensões são carregadas com a flag RTLD_LOCAL, garantindo que os símbolos de uma extensão não entrem em conflito com os símbolos de outras extensões. Isso evita colisões de nomes quando várias extensões usam nomes de biblioteca ou nomes de função comuns.
A variável de sistema veb_dir aponta para o diretório onde os arquivos de extensão .veb são armazenados.

Fluxo de Desinstalação

Prevenção de dependências: Não é possível desinstalar se colunas de tabelas usarem os tipos personalizados da extensão.

Estrutura do Diretório de Expansão

O VillageSQL expande arquivos .veb no diretório de dados do MySQL para oferecer suporte a várias versões:
Por que diretórios SHA256?
  • Testar novas versões sem sobrescrever
  • Habilitar reversão
  • Evitar “mesma versão, código diferente”
Limpeza: Diretórios SHA256 órfãos são removidos na reinicialização do servidor.

Camada de Cache do Victionary

O VictionaryClient mantém caches em memória dos metadados do sistema para buscas O(log n).

Operações de Cache

Invalidação de cache: Automática durante operações DDL (INSTALL/UNINSTALL EXTENSION). Sobrecarga de memória: ~100 bytes por entrada.

Sistema de Tipos Personalizados

Resolução de Tipo

Tipos de Implementação

Os tipos personalizados são mapeados para tipos de armazenamento do MySQL:

Comportamento de Concorrência e Transações

Modelo de Segurança de Threads

As funções de extensão são chamadas em um modelo de execução por linha:
  • Execução isolada por linha: Cada chamada de função recebe seu próprio buffer de resultado (thread-safe por design)
  • Ganchos Prerun/Postrun: Configuração/limpeza por instrução, chamados uma vez por instrução SQL
  • Sem isolamento garantido: Várias conexões podem chamar suas funções simultaneamente
  • Prática recomendada: Evite estado global; use parâmetros de função e valores de retorno
O VillageSQL não garante isolamento de threads para funções de extensão. Se você usar variáveis globais ou estado compartilhado, proteja-os com mutexes ou bloqueios.

Comportamento de Transações

As funções de extensão devem seguir estas práticas recomendadas:
  • Projete funções para serem sem estado quando possível
  • Evite efeitos colaterais persistentes (escritas em arquivo, chamadas a APIs externas) nas funções
  • Se usar estado prerun/postrun, trate a limpeza adequadamente

Considerações de Desempenho

Otimização: Use ganchos prerun para armazenar em cache configurações caras por instrução em vez de repetir o trabalho por linha.

Desempenho de Tipos Personalizados


Segurança e Depuração

Modelo de Segurança

Modelo de confiança: As extensões são executadas com privilégios completos do servidor.
  • Sem sandbox ou sistema de permissões
  • As extensões podem ler qualquer arquivo, acessar a rede, executar código
  • Implicações de confiança: Instale apenas extensões de fontes confiáveis
Segurança de instalação: Executa como usuário villagesql_extension_installer (troca de contexto).
Habilitar log detalhado:
Depuração com GDB:
Verificar dependências:
Erros comuns:
  • Undefined symbol: Verifique as dependências da biblioteca com ldd (Linux) ou otool -L (macOS)
  • Cannot open shared object: Verifique se as dependências da biblioteca estão presentes e vinculadas corretamente
  • Crash on VDF call: Verifique o tratamento de pointers NULL

Próximos Passos

Criando Extensões em C++

Crie sua primeira extensão

Referência do Sistema

Tabelas e visões do sistema

Exemplos de Extensões em C++

Estude a implementação do vsql_complex

Gerenciando Extensões

Monitore e solucione problemas