RATIONAL, VECTOR ou INET, que funcionam com ORDER BY, índices e funções de agregação. O SDK Rust oferece suporte a isso por meio da macro custom_type! e, para tipos cujo tamanho de armazenamento depende de parâmetros de coluna, por meio de parameterized_type! (consulte Tipos parametrizados).
Esta página pressupõe que você já tenha trabalhado com Criando Extensões em Rust. A configuração (Cargo.toml, manifest.json, cargo-vsql) é a mesma.
Quando usar um tipo personalizado
Use um tipo personalizado quando:- Você precisar de um layout binário em disco que um tipo SQL padrão não consegue expressar (floats compactados, inteiros de largura fixa, identificadores binários)
- Seu tipo tiver semântica de ordenação própria que difere da ordenação lexicográfica de strings
- Você quiser que o servidor indexe e faça hash dos valores corretamente para
ORDER BY,COUNT(DISTINCT)e operações de conjunto
STRING, INT ou REAL, você não precisa de um tipo personalizado.
A macro custom_type!
Todo tipo personalizado precisa de 4 callbacks (encode, decode, compare, hash) e um valor padrão. Aqui está a assinatura completa da macro:type_name, persisted_length, max_decode_buffer_length, encode, decode e compare são obrigatórios. hash e default são opcionais, mas recomendados — hash é necessário para que o COUNT(DISTINCT) e as operações de conjunto funcionem corretamente, e default é necessário para a verificação de inicialização do tipo.
Recebendo e retornando valores binários
Funções que recebem ou retornam um tipo personalizado trabalham com bytes brutos. Entrada —InValue::Custom(b) carrega o binário armazenado como &[u8]:
VdfReturn::Binary(bytes) envia bytes binários de volta ao servidor:
func!, use villagesql::custom!("type_name"):
Exemplo: tipo de número racional
examples/vsql_rational no repositório do SDK é uma extensão funcional que implementa um tipo RATIONAL. Ela armazena um número racional como um par de valores i64 (numerador, denominador, totalizando 16 bytes) em ordem de bytes little-endian e fornece funções aritméticas.
Aqui estão as implementações principais de encode, decode, compare e hash:
custom_type! e as VDFs aritméticas (rational_add, rational_sub, etc.) estão no código-fonte completo em examples/vsql_rational/src/lib.rs.
Com a extensão instalada:
rational_to_real(r RATIONAL) -> REAL converte um valor RATIONAL em uma aproximação de ponto flutuante de 64 bits, dividindo o numerador pelo denominador. Útil quando você precisa de um decimal aproximado para exibição ou comparação, mas não quer armazenar a representação com perda na coluna.
Tipos parametrizados
Um tipo parametrizado precisa de um valor lido no momento doCREATE TABLE — como
o 3 em VECTOR(3) — para saber seu tamanho de armazenamento. custom_type! não
consegue expressar isso: seu persisted_length é uma única constante fixa para toda
coluna. parameterized_type! é a contraparte parametrizada: o comprimento persistido
é calculado por coluna a partir dos parâmetros declarados, através de int_to_params
e resolve_params, em vez de ser fixo.
type_name, max_persisted_length, max_decode_buffer_length, encode, decode, compare, int_to_params, resolve_params, params_type, params_parse e params_to_strings são obrigatórios. hash e default são opcionais; intrinsic_default_fn (uma função que calcula o padrão a partir de &P, para quando o padrão depende dos parâmetros) também é opcional e mutuamente exclusiva com default.
Aqui está padint — um i64 armazenado em 8 bytes fixos, com um parâmetro width que controla a largura de exibição preenchida com zeros:
InValue::CustomWithParams { bytes, params } em vez do simples
InValue::Custom(bytes) — params é um [TypeParams], uma visão somente de
leitura e sem cópia sobre os pares key=value declarados da coluna.
O bloco extension! com tipos
Ao registrar tanto funções quanto tipos, o blocoextension! tem duas seções:
types:. Uma extensão que contém apenas tipos mantém funcs: [] e não omite mais nada.
Próximos passos
Referência da API Rust
Referência completa para InValue, VdfReturn e todas as macros.
Criando Extensões em Rust
Primeiros passos — configuração do Cargo, primeira função, empacotamento e testes.
Tipos Personalizados em C++
Tipos personalizados em C++ —
make_type<>, encode/decode/compare/hash, regras de ALTER TABLE.Arquitetura de Extensões
Como tipos personalizados são resolvidos, armazenados em cache e persistidos.

