Skip to main content
Os tipos personalizados usam o VEF Protocol 3, estável a partir da v0.0.4. O Protocol 4 está em desenvolvimento e está disponível apenas por meio dos cabeçalhos opt-in da dev ABI (-DVSQL_USE_DEV_ABI=ON). Extensões compiladas contra o antigo Protocol 2 são rejeitadas pelo servidor e precisam ser recompiladas.
Os tipos personalizados permitem que você defina novos tipos de coluna (como COMPLEX, UUID ou VECTOR) que funcionam com ORDER BY, índices e funções de agregação. Esta página é o Passo 4 do tutorial Criando Extensões em C++. Conclua os Passos 1 a 3 antes de continuar aqui.

Definir as Operações de Tipo

Todo tipo personalizado precisa de operações de codificação, decodificação e comparação e, opcionalmente, de uma operação de hash. Implemente-as de acordo com estas assinaturas e passe os objetos builder para vsql::make_type<>():
Para uma VDF from_string (que retorna o tipo personalizado), o servidor dimensiona o buffer de saída para pelo menos o valor persisted_length do tipo antes de invocar a VDF, portanto buf.size() >= persisted_length é garantido na entrada. Isso se aplica tanto a tipos de largura fixa quanto a tipos parametrizados (onde persisted_length é resolvido a partir do contexto do tipo no momento da chamada). Nenhuma solicitação separada de tamanho de buffer é necessária.
O acesso binário bruto passa por vsql::Span<T>, uma visão não proprietária sobre uma sequência contígua de Tin.value() retorna vsql::Span<const unsigned char> e out.buffer() retorna vsql::Span<unsigned char>. Usando C++20 ou posterior, vsql::Span<T> é um alias para std::span<T>; sob C++17, o SDK C++ fornece uma implementação de fallback mínima e compatível em nível de código-fonte, com a mesma superfície de data(), size(), empty(), indexação e iteradores. Ela está disponível por meio de #include <villagesql/vsql.h>.

Registrar o Tipo

O template vsql::make_type<kName>() incorpora as operações de codificação, decodificação, comparação e hash diretamente no objeto do tipo. Os nomes das VDFs são gerados automaticamente como TYPE::from_string, TYPE::to_string, TYPE::compare e TYPE::hash em tempo de compilação. Chamadas separadas de .func(make_type_encode<>(...)) não são necessárias.
build() falha na compilação se from_string, to_string ou compare estiver ausente. Cada método de template valida a assinatura do pointer de função com static_assert. O nome do tipo é passado como um parâmetro de template que não é de tipo (NTTP). Declare-o como um array static constexpr const char[] — a identidade do pointer é usada como chave para buffers independentes de nomes de VDF, portanto dois tipos que compartilham um pointer de função ainda obtêm nomes gerados automaticamente separados.

Referência das Operações de Tipo

A API baseada em template gera automaticamente estas VDFs que podem ser chamadas via SQL: Consulte Operações de Tipo para as assinaturas C++ completas.

ALTER TABLE e Tipos Personalizados

ALTER TABLE ... MODIFY COLUMN e CHANGE COLUMN aplicam estas regras quando tipos personalizados estão envolvidos:

Funções de Conversão de Tipo

Com a API baseada em template, as VDFs de codificação e decodificação são incorporadas no objeto do tipo e registradas automaticamente — nenhuma chamada separada de .func() é necessária. As VDFs geradas automaticamente podem ser chamadas via SQL:
Quando a conversão explícita é necessária. O VillageSQL converte implicitamente um literal de string para um tipo personalizado em atribuição direta de coluna, então INSERT INTO t (val) VALUES ('(1.0,2.0)') funciona sem uma chamada explícita. Mas expressões que resolvem para o tipo STRING, como expressões CASE, CONCAT e similares, não sofrem coerção implícita. Envolva-as com TYPE::from_string:

Exemplo: Tipo COMPLEX

Aqui está um exemplo completo implementando um tipo de número COMPLEX:
Depois de definir essas operações, os usuários podem criar tabelas com o seu tipo personalizado:

VDFs em Colunas Geradas

As VDFs podem ser usadas em expressões de colunas geradas. A VDF precisa ser declarada como .deterministic() no builder da extensão — o servidor bloqueia funções não determinísticas neste contexto.
complex_abs precisa ser registrada com .deterministic(). UDFs tradicionais do MySQL não são permitidas em colunas geradas.
Consulte Exemplo vsql_complex para a implementação completa.

VDFs em Índices Funcionais

As VDFs podem ser usadas em expressões de índices funcionais. O mesmo requisito de .deterministic() das colunas geradas se aplica aqui, porque o MySQL implementa índices funcionais como colunas geradas ocultas.
O otimizador usa o índice quando a mesma expressão de VDF aparece em WHERE, ORDER BY ou GROUP BY. Faça o cast do valor de comparação para o tipo de retorno da VDF, de modo que o otimizador corresponda à expressão:

Próximos Passos

Quando o seu tipo estiver definido, continue com o Passo 5 do tutorial para compilar e instalar a sua extensão.

Continuar: Compile a Sua Extensão

Volte ao tutorial para compilar e instalar a sua extensão.

Tipos Parametrizados

Tipos que recebem parâmetros como VECTOR(1536) — codificação, decodificação e dimensionamento de armazenamento cientes da dimensão.

Referência da API C++

Contratos da API de VDFs, tratamento de null, dimensionamento de buffer e padrões avançados.

Replicação

Requisitos do formato ROW, ordem de instalação de extensões e correspondência de versões para configurações replicadas.