> ## 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 Rust

> Comece a usar o SDK Rust do VillageSQL — escreva funções de extensão em Rust seguro, empacote-as como arquivos VEB e instale-as no VillageSQL.

> [!NOTE]
>
> Se você prefere C++, consulte [Criando Extensões em C++](https://villagesql.com/docs/pt-BR/extensions/build/create.md) para o guia passo a passo do SDK C++.

As extensões do VillageSQL podem ser escritas em Rust usando a crate `villagesql`. O SDK cuida de todo o marshaling de FFI — você trabalha com tipos Rust comuns e a macro `extension!` gera os pontos de entrada C que o servidor chama no momento do carregamento.

## Pré-requisitos

Antes de começar, compile o VillageSQL a partir do código-fonte — `cargo vsql install` e `cargo vsql test` usam a árvore de compilação do servidor. Siga primeiro o guia [Compilar a Partir do Código-Fonte](https://villagesql.com/docs/pt-BR/8.4/stable/source.md).

Você também precisa de:

* **Toolchain estável do Rust** — instale em [rustup.rs](https://rustup.rs)
* **Git** — para clonar o SDK e o repositório da sua extensão
* **cargo-vsql** — o subcomando do Cargo para empacotar, instalar e testar extensões
* **Diretório de compilação do VillageSQL** — defina `VillageSQL_BUILD_DIR` como o caminho de compilação do seu servidor para `cargo vsql install` e `cargo vsql test`
* **Conhecimento básico de Rust** — familiaridade com Cargo, enums e correspondência de padrões

Instale o `cargo-vsql` a partir do repositório do SDK:

```bash theme={null}
git clone https://github.com/villagesql/vsql-rust-sdk
cd vsql-rust-sdk
cargo install --path cargo-vsql
```

Verifique se está disponível:

```bash theme={null}
cargo vsql --help
```

## Crie uma nova crate

Crie uma nova crate de biblioteca Rust e adicione o SDK:

```bash theme={null}
cargo new --lib vsql_rot13
cd vsql_rot13
cargo add villagesql
```

Em seguida, defina o tipo da crate no `Cargo.toml`:

```toml theme={null}
[lib]
crate-type = ["cdylib"]
```

O tipo de crate `cdylib` diz ao Cargo para produzir uma biblioteca compartilhada (`.so` no Linux, `.dylib` no macOS) que o servidor pode carregar.

## Escreva sua primeira função

Substitua `src/lib.rs` por uma extensão completa:

```rust theme={null}
use villagesql::{InValue, VdfReturn};

fn rot13_impl(args: &[InValue]) -> VdfReturn {
    match args.first() {
        Some(InValue::String(s)) => VdfReturn::string(rot13(s)),
        Some(InValue::Null) | None => VdfReturn::null(),
        _ => VdfReturn::error("vsql_rot13: expected a STRING argument"),
    }
}

fn rot13(s: &str) -> String {
    s.chars()
        .map(|c| match c {
            'a'..='m' | 'A'..='M' => (c as u8 + 13) as char,
            'n'..='z' | 'N'..='Z' => (c as u8 - 13) as char,
            _ => c,
        })
        .collect()
}

villagesql::extension! {
    funcs: [
        villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String),
    ]
}
```

A macro `func!` conecta `rot13_impl` ao nome SQL `vsql_rot13` com uma assinatura `STRING -> STRING`.

A assinatura da função é `fn(&[InValue]) -> VdfReturn`. `InValue` é um enum sobre os tipos SQL que o servidor passa. `VdfReturn` é o que você retorna. Verifique `args.first()` para tratar tanto o caso NULL quanto o caso de tipo incorreto antes de acessar o valor.

Se a sua função sempre retorna a mesma saída para as mesmas entradas, declare-a como determinística — somente uma função determinística pode aparecer em uma coluna gerada ou em uma restrição `CHECK`:

```rust theme={null}
villagesql::func!(rot13_impl, "vsql_rot13", [villagesql::Type::String] -> villagesql::Type::String, deterministic: true)
```

## Adicione o manifest.json

Crie o `manifest.json` na raiz da crate (ao lado do `Cargo.toml`):

```json theme={null}
{
  "name": "vsql_rot13",
  "version": "0.1.0",
  "description": "ROT-13 encoding for VillageSQL",
  "author": "Your Name",
  "license": "GPL-2.0"
}
```

O servidor lê isso no momento da instalação. O campo `name` deve corresponder ao `name` na seção `[package]` do `Cargo.toml` e ao que você passa para `INSTALL EXTENSION`.

## Compile e instale

> [!NOTE]
>
> Execute `cargo vsql package`, `cargo vsql install` e `cargo vsql test` de dentro do diretório da extensão (onde ficam o `Cargo.toml` e o `manifest.json`), não da raiz do workspace.

Empacote a extensão em um arquivo `.veb`:

```bash theme={null}
cargo vsql package
```

Isso produz `dist/vsql_rot13.veb`. Para empacotar e copiar o VEB diretamente para o seu diretório de compilação do VillageSQL:

```bash theme={null}
export VillageSQL_BUILD_DIR=/path/to/villagesql/build
cargo vsql install
```

Para aplicar um patch em uma dependência apontando para um checkout local durante o desenvolvimento, passe `--config KEY=VALUE` (repetível):

```bash theme={null}
cargo vsql install --config 'patch.crates-io.villagesql.path="/path/to/villagesql"'
```

Você deve ver o VEB copiado para o diretório de extensões. Verifique se ele está lá:

```bash theme={null}
ls "$VillageSQL_BUILD_DIR/veb_output_directory/"
# vsql_rot13.veb
```

> [!NOTE]
>
> **Alterado na versão 0.0.8-dev.** `cargo vsql install` copia o VEB para `$VillageSQL_BUILD_DIR/lib/veb/`.

## Teste

Escreva um arquivo de teste em `mysql-test/t/rot13_basic.test`:

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
SELECT vsql_rot13('Hello');
SELECT vsql_rot13('');
SELECT vsql_rot13(NULL);
UNINSTALL EXTENSION vsql_rot13;
```

Gere os resultados esperados:

```bash theme={null}
cargo vsql test --record
```

Execute a suíte:

```bash theme={null}
cargo vsql test
```

Após modificar o comportamento da sua função, execute novamente `cargo vsql test --record` para atualizar os resultados esperados e, em seguida, `cargo vsql test` para confirmar.

## Instale em SQL

Assim que o VEB estiver no diretório de extensões, instale-o:

```sql theme={null}
INSTALL EXTENSION vsql_rot13;
```

Verifique:

```sql theme={null}
SELECT * FROM INFORMATION_SCHEMA.EXTENSIONS WHERE EXTENSION_NAME = 'vsql_rot13';
```

Chame-a:

```sql theme={null}
SELECT vsql_rot13('Hello, World!');
-- → Uryyb, Jbeyq!
```

## Próximos passos

Este passo a passo cria uma única função escalar. Dois exemplos completos no repositório [vsql-rust-sdk](https://github.com/villagesql/vsql-rust-sdk) cobrem, em vez disso, o suporte a agregações e varargs:

* [`examples/vsql_agg_sum`](https://github.com/villagesql/vsql-rust-sdk/tree/main/examples/vsql_agg_sum) — uma VDF de agregação que reimplementa `SUM` com `agg_func!`, usando callbacks separados `clear`, `accumulate` e `result` sobre um acumulador por grupo.
* [`examples/vsql_varargs`](https://github.com/villagesql/vsql-rust-sdk/tree/main/examples/vsql_varargs) — quatro funções varargs criadas com `varargs_func!`: `str_join` (validada, com estado), `arg_count` (sem validação, sem estado), `describe` (validada, sem estado, argumentos heterogêneos INT/REAL/STRING) e `point_path` (varargs sobre um tipo personalizado `point2d`).

Cada exemplo inclui um `Cargo.toml`, um `manifest.json` e um teste MTR completos.

> [card] [Tipos Personalizados em Rust](https://villagesql.com/docs/pt-BR/sdk/rust/custom-types.md)
>
> Defina novos tipos de coluna com armazenamento binário, ordenação e hashing.

> [card] [Referência da API Rust](https://villagesql.com/docs/pt-BR/sdk/rust/api-reference.md)
>
> InValue, VdfReturn, extension!, func! e custom\_type! — todos os campos.

> [card] [Capabilities Preview em Rust](https://villagesql.com/docs/pt-BR/sdk/rust/preview-capabilities.md)
>
> Variáveis de status, variáveis de sistema, thread workers em segundo plano e
> acesso ao keyring por meio da lista requires:.

> [card] [SDK C++ (Criando Extensões em C++)](https://villagesql.com/docs/pt-BR/extensions/build/create.md)
>
> O caminho C++ — wrappers tipados, API de builder e configuração do CMake.

> [card] [Arquitetura de Extensões](https://villagesql.com/docs/pt-BR/extensions/build/architecture.md)
>
> Como os arquivos VEB são carregados, hooks de ciclo de vida e isolamento de símbolos.

> [card] [Testando Extensões Dependentes de Rede](https://villagesql.com/docs/pt-BR/sdk/cpp/testing-network.md)
>
> Padrões de porta do MTR para extensões que iniciam servidores HTTP ou listeners externos — aplica-se igualmente a extensões Rust e C++.


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