> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Criando Extensões em C++

> Aprenda a criar extensões personalizadas do VillageSQL em C++ usando o template de extensão e o VEF.

> [!WARNING]
>
> O Protocol 3 do VEF é estável a partir da v0.0.4. O Protocol 4 está em desenvolvimento e disponível apenas por meio de cabeçalhos opcionais da dev ABI (`-DVSQL_USE_DEV_ABI=ON`). Extensões compiladas com o antigo Protocol 2 são rejeitadas pelo servidor e precisam ser recompiladas.

## Visão geral

O framework de extensões do VillageSQL (VEF) permite adicionar funcionalidades personalizadas ao servidor de banco de dados. Este guia percorre a criação de uma extensão em C++ usando o SDK C++ e o template de extensão.

Para escrever implementações de VDF em profundidade (como tipos de argumento e de retorno, agregados, variáveis de sistema e tipos parametrizados), consulte o [Guia de Desenvolvimento](https://villagesql.com/docs/pt-BR/sdk/cpp/development.md).

> [!NOTE]
>
> Se você prefere Rust, consulte [Criando Extensões em Rust](https://villagesql.com/docs/pt-BR/extensions/build/rust-sdk.md).

## O que é uma Extensão do VillageSQL?

Uma extensão do VillageSQL é empacotada como um **arquivo VEB** (VillageSQL Extension Bundle) contendo:

* **Manifesto** - Metadados sobre a extensão (nome, versão, descrição)
* **Biblioteca compartilhada** - Código C++ compilado que implementa a funcionalidade
* **Metadados opcionais** - Recursos ou configurações adicionais

Extensões em C++ são compiladas usando o **SDK C++**, a ligação C++ para o VEF (o VillageSQL Extension Framework). Ele fornece:

* API C++ para definir tipos e funções
* Registro automático sem scripts SQL
* Tipos de argumento e de retorno com segurança de tipos
* Padrão de builder para a definição da extensão

> [!NOTE]
>
> **VDFs vs UDFs tradicionais:** Funções registradas por meio do VEF são chamadas de VDFs (VillageSQL Defined Functions). O VillageSQL também oferece suporte a UDFs tradicionais do MySQL registradas via `CREATE FUNCTION ... SONAME`, mas VDFs são recomendadas para novas extensões.

### Chamando VDFs em SQL

VDFs podem ser chamadas com ou sem o prefixo da extensão:

```sql theme={null}
-- Unqualified (preferred for cleaner code)
SELECT complex_abs(impedance) FROM signals;

-- Qualified with extension name (explicit)
SELECT vsql_complex.complex_abs(impedance) FROM signals;
```

**Ordem de resolução de funções:**

Quando você chama uma função sem qualificação, o VillageSQL a resolve nesta ordem:

1. **Funções de sistema** (funções nativas do MySQL como `NOW()`, `CONCAT()`)
2. **UDFs** (funções tradicionais definidas pelo usuário do MySQL)
3. **VDFs** (funções de extensão) - apenas se houver exatamente uma função com esse nome
4. **Funções armazenadas** (criadas com `CREATE FUNCTION`)

**Quando usar nomes qualificados:**

* Use `extension.function_name` quando várias extensões fornecem funções com o mesmo nome
* Use nomes não qualificados para um código mais limpo quando não houver ambiguidade
* A qualificação não é obrigatória se apenas uma extensão fornecer aquele nome de função e nenhuma função de sistema ou UDF tiver o mesmo nome

Extensões podem adicionar:

* **Funções personalizadas (VDFs)** - Funções SQL com verificação e validação de tipos automáticas
* **Tipos de dados personalizados** - Novos tipos de coluna como COMPLEX, UUID ou VECTOR que funcionam com ORDER BY e índices
* **Operações de tipo** - Funções de encode, decode, compare e hash para tipos personalizados

## Pré-requisitos

Antes de começar, você precisa do SDK de Extensões do VillageSQL, e há duas formas de apontar o CMake para um deles. Se você tem uma árvore de compilação do VillageSQL, passe `-DVillageSQL_BUILD_DIR=/path/to/villagesql/build` — o guia [Compilar a Partir do Código-Fonte](https://villagesql.com/docs/pt-BR/8.4/stable/source.md) produz essa árvore. Se você tem um diretório de SDK descompactado — um que contenha `include/villagesql/vsql.h` —, isso basta por si só: passe `-DVillageSQL_SDK_DIR=/path/to/sdk`. O [README do template de extensão](https://github.com/villagesql/vsql-extension-template) explica como obter um SDK sem compilar o servidor. Somente a forma com árvore de compilação define um diretório de instalação de VEB, então, no caminho apenas com SDK, copie você mesmo o arquivo VEB compilado para o diretório que `SHOW VARIABLES LIKE 'veb_dir'` informar.

Você também precisa de:

* **Git** - Para clonagem e controle de versão
* **CMake** 3.18 ou superior - Sistema de compilação
* **Compilador C++** - Com suporte a C++17: o template define `CMAKE_CXX_STANDARD 17`, e seu `FindVillageSQL.cmake` rejeita um padrão inferior
* **Conhecimento básico de C++** - Compreensão de C++ e pointers de função

> [!TIP]
>
> **Compilando com um agente de IA?** A skill [`vsql-extension-builder`](https://github.com/villagesql/villagesql-skills) automatiza todo esse fluxo de trabalho, da estruturação aos testes, usando Claude Code, Antigravity ou outros agentes compatíveis. Instale-a com:
>
> ```bash theme={null}
> curl -sSL https://villagesql.com/skills | bash
> ```

## Passo 1: Obtenha o Template de Extensão

Você pode começar com o template de extensão de duas maneiras:

### Opção A: Usar o Template a Partir do Código-Fonte do VillageSQL

Se você compilou o VillageSQL a partir do código-fonte, copie o template da árvore de código-fonte e configure-o no Passo 7 com `-DCMAKE_PREFIX_PATH=/path/to/villagesql/build/villagesql-extension-sdk-<version>`:

```bash theme={null}
cd /path/to/villagesql-source
cp -r villagesql/sdk/template my-extension
cd my-extension
```

### Opção B: Fazer um Fork no GitHub

Comece fazendo um fork do repositório do template de extensão do VillageSQL:

1. Acesse o repositório do template no GitHub:
   ```
   https://github.com/villagesql/vsql-extension-template
   ```

2. Clique no botão **"Fork"** para criar sua própria cópia

3. Clone seu fork localmente:
   ```bash theme={null}
   git clone https://github.com/YOUR_USERNAME/vsql-extension-template.git
   cd vsql-extension-template
   ```

> [!TIP]
>
> Como alternativa, use o botão "Use this template" no GitHub para criar um novo repositório baseado no template sem o histórico do fork.

## Passo 2: Atualize o Manifesto

Edite `manifest.json` para definir os metadados da sua extensão:

```json theme={null}
{
  "$schema": "https://raw.githubusercontent.com/villagesql/villagesql-docs/main/mysql-8.4/stable/manifest.json.schema.json",
  "name": "my_awesome_extension",
  "version": "1.0.0",
  "description": "My custom VillageSQL extension that does amazing things",
  "author": "Your Name",
  "license": "GPL-2.0"
}
```

O campo `$schema` é opcional, mas habilita o autocompletar da IDE e a validação inline
para todos os campos do manifesto.

### Esquema do manifest.json

| Campo | Obrigatório | Formato | Descrição |
| - | - | - | - |
| `name` | ✅ Sim | letras, dígitos, `_`, `-` | Identificador único. Deve corresponder ao nome em `INSTALL EXTENSION`. |
| `version` | ✅ Sim | MAJOR.MINOR.PATCH | String de versão semântica |
| `description` | Não | String | Breve explicação da funcionalidade |
| `author` | Não | String | Nome do autor ou organização |
| `license` | Não | String | Identificador de licença (GPL-2.0 recomendado) |

**Regras de validação:**

* `name`: Deve começar com uma letra e terminar com uma letra ou dígito. Pode conter letras minúsculas, dígitos, sublinhados e hifens. Máximo de 64 caracteres. **Use sublinhados** — hifens exigem uso de crases (backticks) em SQL.
* `version`: Deve seguir o versionamento semântico (ex.: 1.0.0, 0.2.1)
* `INSTALL EXTENSION` falha quando `name` ou `version` está ausente, ou quando `name` viola a regra de início, fim, caracteres ou comprimento

**Exemplo:**

```sql theme={null}
-- manifest.json has "name": "my_awesome_extension"
INSTALL EXTENSION my_awesome_extension;  -- ✅ Correct: no quoting needed
-- manifest.json has "name": "my-awesome-extension"
INSTALL EXTENSION `my-awesome-extension`;  -- ⚠️ Works, but requires backtick quoting
```

Para a convenção de nomenclatura completa em SQL, nomes de arquivo e nomes de repositório, consulte [Convenções de Nomenclatura de Extensões](https://villagesql.com/docs/pt-BR/extensions/install.md#extension-naming-conventions).

## Passo 3: Implemente Sua Extensão com o SDK C++

O SDK C++ fornece uma API C++ para definir extensões usando um padrão de builder fluente:

* Definições de função com segurança de tipos e verificação em tempo de compilação
* Validação automática de argumentos e conversão de tipos
* Suporte a tipos personalizados com funções compare/hash (habilita ORDER BY e índices)

### Inclua os Cabeçalhos do VillageSQL

Crie o arquivo principal da sua extensão (ex.: `src/extension.cc`) e inclua os cabeçalhos do SDK C++:

```cpp theme={null}
#include <villagesql/vsql.h>

// Your implementation code here
```

O cabeçalho `<villagesql/vsql.h>` traz o builder de tipos, o builder de funções e
o builder de extensão, e reexporta símbolos comumente usados para o namespace `vsql`.

### Defina Sua Extensão

Use a macro `VEF_GENERATE_ENTRY_POINTS()` para definir sua extensão:

```cpp theme={null}
VEF_GENERATE_ENTRY_POINTS(
  make_extension()
    .func(make_func<&my_reverse_impl>("my_reverse")
      .returns(STRING)
      .param(STRING)
      .build())
    .func(make_func<&count_vowels_impl>("count_vowels")
      .returns(INT)
      .param(STRING)
      .build())
);
```

**Métodos do Builder de Função:**

* `make_func<&impl>("name")` - Cria a função com o pointer de implementação
* `.returns(type)` - Define o tipo de retorno (STRING, INT, REAL ou nome de tipo personalizado)
* `.param(type)` - Adiciona um parâmetro (máximo de 8 parâmetros)
* `.buffer_size(size_t)` - Solicita um tamanho de buffer de saída específico para retornos STRING/CUSTOM
* `.max_result_length(size_t)` - Dimensiona a coluna de resultado para um retorno STRING para que um resultado materializado não seja truncado na largura do argumento. Valores acima de `VEF_MAX_RESULT_LENGTH` (16 MiB) são limitados pelo servidor. Somente STRING; chame `.returns(STRING)` primeiro. Requer o Protocol 4 (dev ABI).
* `.deterministic(bool = true)` - Declara que esta função sempre retorna a mesma saída para as mesmas entradas e não tem efeitos colaterais. O padrão é não determinístico.
* `.prerun<func>()` - Define a função de preparação por instrução (opcional)
* `.postrun<func>()` - Define a função de limpeza por instrução (opcional)
* `.build()` - Finaliza o registro da função

> [!NOTE]
>
> **Limite de Parâmetros:** As funções declaradas com `.param()` oferecem suporte a no máximo 8 parâmetros (definido por `kMaxParams`). Se você precisar de mais, considere uma VDF varargs, tipos estruturados ou várias funções.

### VDFs com Argumentos e Valores de Retorno de Tipo Personalizado

Uma VDF pode receber e retornar valores de tipo personalizado usando `.param(TYPE_NAME)` e
`.returns(TYPE_NAME)` no builder. A implementação usa `CustomArg`
para entrada e `CustomResult` para saída — os mesmos tipos de argumento e resultado usados nas operações
de tipo:

```cpp theme={null}
void complex_conjugate_impl(CustomArg in, CustomResult out) {
    if (in.is_null()) { out.set_null(); return; }
    auto src = in.value();    // Span<const unsigned char> — raw binary
    auto dst = out.buffer();  // Span<unsigned char>
    // ... read src, write result to dst ...
    out.set_length(src.size());
}
```

Registre com `.param(COMPLEX)` e `.returns(COMPLEX)`:

```cpp theme={null}
.func(make_func<&complex_conjugate_impl>("complex_conjugate")
          .returns(COMPLEX)
          .param(COMPLEX)
          .build())
```

Consulte o [guia de desenvolvimento](https://villagesql.com/docs/pt-BR/sdk/cpp/development.md#argument-and-result-types)
para a API completa de `CustomArg`/`CustomResult`, incluindo `CustomArgWith<P>`
e `CustomResultWith<P>` para tipos parametrizados.

### Funções Determinísticas

Por padrão, VDFs são registradas como não determinísticas. Uma função não determinística é bloqueada em quatro contextos SQL: colunas geradas, índices funcionais, restrições CHECK e valores padrão de expressão (`DEFAULT (expr)` em uma coluna) — usar qualquer um desses recursos com uma VDF não determinística retorna um erro. Se sua função sempre produz a mesma saída para as mesmas entradas e não tem efeitos colaterais, você pode declará-la determinística adicionando `.deterministic()` à cadeia do builder.

O otimizador pode usar essa informação para avaliar a função uma vez por instrução e reutilizar o valor entre as linhas, em vez de chamá-la por linha. Marcar incorretamente uma função não determinística como determinística pode, portanto, fazer com que o servidor retorne o mesmo resultado para entradas que deveriam produzir saídas diferentes. Adicione `.deterministic()` apenas quando sua função realmente não tiver dependência de estado externo, aleatoriedade ou tempo.

**Assinatura do builder:** `.deterministic(bool d = true)` — a forma sem argumentos assume `true` como padrão.

**Exemplo:**

```cpp theme={null}
.func(make_func<&complex_add_impl>("complex_add")
          .returns(COMPLEX)
          .param(COMPLEX)
          .param(COMPLEX)
          .deterministic()
          .build())
```

Como `complex_add` é declarada determinística, ela pode ser usada em uma definição de coluna gerada:

```sql theme={null}
-- Deterministic VDFs can be used in generated columns
CREATE TABLE t (
    a COMPLEX,
    b COMPLEX,
    result COMPLEX GENERATED ALWAYS AS (complex_add(a, b)) STORED
);
-- STORED vs VIRTUAL follows standard MySQL generated column rules
```

### Tamanhos de Buffer Personalizados

Para funções que retornam dados de comprimento variável, solicite um tamanho de buffer específico:

```cpp theme={null}
make_func<&large_result_impl>("large_result")
  .returns(STRING)
  .param(STRING)
  .buffer_size(65536)  // Request 64KB buffer
  .build()
```

Quando você mesmo constrói o valor com `buffer()` e `set_length()`, nunca escreva
além de `buffer().size()` — isso causa estouro de memória. Mas também não falhe diante de um valor
grande demais: informe o tamanho que você teria escrito e deixe o servidor aumentar
o buffer e chamar você novamente.

```cpp theme={null}
void large_result_impl(StringArg input, StringResult out) {
    if (input.is_null()) { out.set_null(); return; }
    size_t needed = calculate_output_size(input.value());

    auto buf = out.buffer();
    if (needed > buf.size()) {
        // Too small this time. Report what is needed and return: the server
        // grows the buffer to `needed` and re-invokes this function, and the
        // second call takes the branch below.
        out.set_length(needed);
        return;
    }

    // Write output into buf.data()
    out.set_length(actual_output_length);
}
```

Com os headers da ABI de desenvolvimento (`-DVSQL_USE_DEV_ABI=ON`), `out.set(sv)` segue um contrato de estouro no estilo snprintf: ele
copia quantos bytes couberem em `out.buffer()`, mas informa o tamanho *total* do
valor. O servidor detecta que o tamanho informado excede o buffer, aumenta o
buffer e chama a função uma segunda vez — de modo que um valor maior que
`.buffer_size()` é retornado por inteiro em vez de truncado. Uma única nova tentativa sempre
basta, porque o tamanho informado diz exatamente qual deve ser a capacidade do buffer.
Com os headers da ABI estável, `out.set(sv)` trunca o valor para `out.buffer().size()`; use `out.buffer()` e `out.set_length()` como acima.

O crescimento é limitado por `max_allowed_packet`. Um valor maior que isso é retornado
como `NULL`, e não truncado.

Escrever em `out.buffer()` e chamar `out.set_length()` por conta própria participa
do mesmo contrato: informe o tamanho total que você teria escrito, e não o número
de bytes que couberam. Informar o tamanho truncado anula a nova tentativa e descarta
silenciosamente o restante.

Esse contrato se aplica no momento da linha. Um resultado STRING *materializado* em uma
tabela temporária de GROUP BY/DISTINCT ou UNION ainda é truncado na largura do argumento,
e `CREATE TABLE ... SELECT` falha no modo SQL estrito com
`ERROR 1406 (22001): Data too long for column '<col>' at row 1`, a menos que a
função declare `.max_result_length(n)`, que dimensiona a coluna de resultado (em
caracteres, limitada a `VEF_MAX_RESULT_LENGTH`, 16 MiB):

```cpp theme={null}
make_func<&large_result_impl>("large_result")
  .returns(STRING)
  .param(STRING)
  .max_result_length(65536)
  .build()
```

> [!NOTE]
>
> Solicite um tamanho de buffer suficiente via `.buffer_size()` com base no tamanho máximo de saída da sua função. Dimensionar o buffer corretamente evita o custo de um ciclo de aumento-e-nova-tentativa.

> [!NOTE]
>
> Antes de implementar suas funções, revise a [Referência da API C++](https://villagesql.com/docs/pt-BR/sdk/cpp/extension-api-reference.md) para os contratos completos de VDF: verificação de null, tipos de resultado, dimensionamento de buffer e tratamento de erros.

## Passo 4: Criando Tipos Personalizados

Tipos personalizados permitem definir novos tipos de coluna — como `COMPLEX`, `UUID` ou
`VECTOR` — que funcionam com `ORDER BY`, índices e funções de agregação.
Se sua extensão registra apenas funções, pule para o Passo 5.

Consulte [Tipos Personalizados em C++](https://villagesql.com/docs/pt-BR/sdk/cpp/custom-types.md) para o passo a passo completo
da implementação. Se seu tipo recebe parâmetros (ex.: `VECTOR(1536)`),
consulte [Tipos Parametrizados](https://villagesql.com/docs/pt-BR/sdk/cpp/type-operations.md#parameterized-types).

## Passo 5: Atualize a Configuração de Compilação

Edite `CMakeLists.txt` para compilar sua extensão como um arquivo VEB:

```cmake theme={null}
cmake_minimum_required(VERSION 3.18)
project(my_extension)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find VillageSQL Extension Framework
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(VillageSQL REQUIRED)
include_directories(${VillageSQLExtensionFramework_INCLUDE_DIR})

# The template's cmake/FindVillageSQL.cmake finds the SDK in this order:
# 1. VillageSQL_BUILD_DIR
# 2. VillageSQL_SDK_DIR
# 3. villagesql_config on PATH
# 4. ~/.villagesql

# Build shared library with your source files
add_library(extension SHARED
    src/extension.cc
)

# Create VEB archive
VEF_CREATE_VEB(
    NAME my_awesome_extension
    LIBRARY_TARGET extension
    MANIFEST ${CMAKE_CURRENT_SOURCE_DIR}/manifest.json
)

```

**Notas de configuração:**

* `VillageSQLExtensionFramework` fornece helpers do CMake para compilar extensões
* `VEF_CREATE_VEB()` empacota sua biblioteca, manifesto e metadados em um arquivo `.veb`
* O `FindVillageSQL.cmake` encontra o SDK e, com `VillageSQL_BUILD_DIR`, define o diretório de instalação do VEB
* O nome do target da biblioteca é normalmente `extension` (pode ser qualquer um)
* O nome do VEB deve corresponder ao nome no seu manifest.json
* Por padrão, extensões são compiladas com os cabeçalhos da ABI estável. Defina `-DVSQL_USE_DEV_ABI=ON` para compilar com os cabeçalhos instáveis da dev ABI

***

## Passo 6: Crie um Diretório de Compilação

Crie um diretório de compilação separado:

```bash theme={null}
mkdir build
cd build
```

## Passo 7: Compile com CMake e Make

Configure e compile sua extensão:

```bash theme={null}
# Configure the build
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVillageSQL_SDK_DIR=/path/to/sdk

# Or, if building against VillageSQL source:
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVillageSQL_BUILD_DIR=/path/to/villagesql/build

# Or, to build against the unstable dev ABI headers:
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DVSQL_USE_DEV_ABI=ON

# Build the extension
make
```

Isso cria:

* Biblioteca compartilhada compilada (arquivo `.so`)
* Pacote VEB (arquivo `.veb`) - um arquivo tar contendo manifesto e biblioteca

### Verifique a Compilação

Verifique o conteúdo do seu arquivo VEB:

```bash theme={null}
make show_veb
```

Você deverá ver:

```
manifest.json
lib/
lib/my_awesome_extension.so
```

## Passo 8: Instale e Teste

### Opção A: Instalar no Diretório de Extensões do VillageSQL

Use o target de instalação para copiar o VEB para sua instalação do VillageSQL:

```bash theme={null}
make install
```

Isso copia o arquivo `.veb` para o diretório configurado via `VillageSQL_VEB_INSTALL_DIR`.

### Opção B: Instalação Manual

Copie o arquivo VEB manualmente:

```bash theme={null}
# Find the VEB directory
mysql -u root -p -e "SHOW VARIABLES LIKE 'veb_dir';"

# Copy the VEB file
sudo cp my_awesome_extension.veb /path/to/veb_dir/
```

### Teste Sua Extensão

1. **Conecte-se ao VillageSQL**:
   ```bash theme={null}
   mysql -u root -p
   ```

2. **Instale a extensão**:
   ```sql theme={null}
   INSTALL EXTENSION my_awesome_extension;
   ```

3. **Verifique a instalação**:
   ```sql theme={null}
   SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS;
   ```

4. **Teste suas funções**:
   ```sql theme={null}
   SELECT my_reverse('Hello, World!');
   -- Output: !dlroW ,olleH

   SELECT count_vowels('VillageSQL');
   -- Output: 3
   ```

## Criando Testes

Adicione arquivos de teste para validar que sua extensão funciona corretamente:

1. **Crie um arquivo de teste** em `mysql-test/t/`:
   ```sql theme={null}
   # mysql-test/t/my_basic.test
   INSTALL EXTENSION my_awesome_extension;
   SELECT my_reverse('abc');
   SELECT my_reverse('');
   SELECT my_reverse(NULL);
   ```

2. **Gere os resultados esperados**:
   ```bash theme={null}
   cd /path/to/villagesql/build/mysql-test
   perl mysql-test-run.pl --suite=/path/to/your/extension/mysql-test --record
   ```

3. **Execute os testes**:
   ```bash theme={null}
   perl mysql-test-run.pl --suite=/path/to/your/extension/mysql-test
   ```

## Solução de Problemas

### A Extensão Não Carrega

Verifique o log de erros e confira o conteúdo do VEB:

```bash theme={null}
make show_veb
tail -f /path/to/error.log
```

### Função Não Encontrada

Verifique a instalação e o registro:

```sql theme={null}
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS;
```

### Erros de Compilação

```bash theme={null}

# Check compiler version
gcc --version  # or clang --version

# Verify CMake version (3.18+ required)
cmake --version
```

## Extensões de Exemplo

Aprenda com extensões existentes do VillageSQL:

> [card] [vsql\_complex](https://github.com/villagesql/villagesql-server/tree/main/villagesql/examples/vsql-complex)
>
> Implementação do tipo de dado de número complexo

> [card] [vsql\_extension\_template](https://github.com/villagesql/vsql-extension-template)
>
> Template mínimo para criar extensões

## Próximos Passos

> [card] [Usando Extensões](https://villagesql.com/docs/pt-BR/extensions/install.md)
>
> Aprenda a instalar e gerenciar extensões

> [card] [Guia de Desenvolvimento](https://villagesql.com/docs/pt-BR/sdk/cpp/development.md)
>
> Tipos de argumento e de retorno, agregados, estado por instrução e varargs

> [card] [Arquitetura de Extensões](https://villagesql.com/docs/pt-BR/extensions/build/architecture.md)
>
> Ciclo de vida, cache, desempenho e modelo de segurança

> [card] [Compilar a Partir do Código-Fonte](https://villagesql.com/docs/pt-BR/8.4/stable/source.md)
>
> Compile o VillageSQL a partir do código-fonte

## Recursos

* [VillageSQL Extension Template](https://github.com/villagesql/vsql-extension-template)
* [MySQL UDF API Documentation](https://dev.mysql.com/doc/extending-mysql/8.4/en/adding-loadable-function.html)
* [CMake Documentation](https://cmake.org/documentation/)
* [VillageSQL Community Discord](https://discord.gg/KSr6whd3Fr)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.