Pré-requisitos
Uma extensão que usa qualquer capability Preview só instala quandovsql_allow_preview_extensions está em ON:
SET GLOBAL é rejeitado para essa variável.
Você também precisa de uma configuração Rust funcional para extensões — o passo
a passo Criando Extensões em Rust cobre a
toolchain, o cargo-vsql e o seu primeiro bloco extension!.
O Que o SDK Rust Envolve
As demais capabilities Preview —
auth, mysql_services, session_var, statement_event, as capabilities de índice personalizado e a ABI de armazenamento de coluna — são exclusivas do C++
hoje. Use o SDK C++ se você
precisar de uma delas.
Padrão de Registro
Declare cada capability como umstatic e então liste-a por referência na seção
requires: de extension! — o equivalente Rust do .with() do SDK C++:
static é obrigatório — o servidor mantém pointers para dentro da
capability durante toda a vida da extensão.
Variáveis de Status
A capabilitystatus_var expõe contadores de propriedade da extensão através de
SHOW GLOBAL STATUS. Sua extensão é dona do armazenamento como atômicos
'static e escreve neles; o servidor lê através dos pointers cada vez que a
variável de status é consultada.
Declare cada variável como um StatusVarSpec — Int respaldado por um
AtomicI64, ou Double respaldado pelo AtomicF64 do SDK (a biblioteca padrão
do Rust não tem um f64 atômico, então o SDK fornece um com new, load e
store):
INSTALL EXTENSION, as variáveis aparecem com o nome da extensão como
prefixo:
Variáveis de Sistema
A capabilitysys_var registra variáveis de sistema do MySQL de propriedade da
sua extensão. Há suporte para três tipos: Bool, Int (com limites
min/max) e Str. Todo spec carrega um nome, um comentário, um valor padrão e um callback
on_change opcional.
Nomes e valores padrão de string são valores &'static CStr — escreva-os como
literais de string C (c"enabled"):
funcs: deve estar presente antes de requires:, mesmo quando vazia.
Após a instalação, as variáveis ficam endereçáveis com o nome da extensão como
prefixo:
Reagindo a Mudanças
on_change é um callback C bruto, invocado pelo servidor depois que uma
variável é definida. O servidor o chama enquanto mantém seu bloqueio global de
variáveis de sistema, então mantenha-o rápido e não gere panic — um panic aqui
atravessa a fronteira da FFI. O callback recebe um
*const vef_sys_var_change_t da camada de ABI bruta:
on_change: Some(on_enabled_change).
Lendo e Escrevendo a partir do Código da Extensão
SysVarCapability também expõe get() e set() para acesso programático
através do servidor (de forma que a validação de intervalo e a persistência
sejam tratadas para você). set() recebe um argumento scope que seleciona a
persistência: null altera apenas o valor em execução, então ele reverte na
reinicialização; "PERSIST" altera o valor em execução e o escreve na
configuração persistida; "PERSIST_ONLY" escreve na configuração persistida sem
tocar no valor em execução, então ele se aplica na próxima reinicialização. Ambos
são métodos FFI unsafe que recebem strings C terminadas em NUL, e
ambos usam a convenção C invertida: Some(false) significa sucesso, Some(true)
significa que o servidor relatou um erro, e None significa que a capability
está indisponível. Em um get bem-sucedido, o servidor escreve uma string
alocada com malloc que você deve liberar com o free() do C. O
exemplo vsql_sys_var
mostra o padrão completo, incluindo o extern do free e os comentários de
segurança.
Thread de Trabalho
A capabilitythread_worker executa uma função que você fornece em uma thread
em segundo plano gerenciada pelo servidor. O servidor registra uma variável de
sistema de controle no momento do carregamento; enquanto ela está em ON, sua
função de trabalho é chamada em um temporizador periódico, na prontidão de um
descritor de arquivo, ou em transições de habilitação/desabilitação.
Sua função de trabalho é Rust seguro e simples:
ThreadWorkerCapability::new recebe a função de trabalho, um sufixo de nome de
thread, o intervalo inicial de espera e um nome alternativo opcional para a
variável de controle. Quando o nome alternativo é None, a variável de controle
se chama {suffix}_enabled e é registrada sob o prefixo da extensão:
Wakeups
WakeupReason diz por que o servidor chamou: Enable, Periodic, PollFd ou
Disable. Seu valor de retorno ajusta o próximo wakeup:
NextWakeup::unchanged()— mantém o intervalo de espera e o poll fd atuais.NextWakeup::after(duration)— acorda novamente apósduration.- Defina o campo
poll_fdcom um descritor de arquivo maior que zero para também acordar quando ele ficar pronto para leitura, ou com-1para limpar um que tenha sido definido antes.
Duration de comprimento zero colapsa para “sem mudança” — a ABI C
subjacente reserva o 0 para isso, então um wakeup instantâneo não pode ser
expresso.
Se a função de trabalho gerar panic, o SDK captura o panic na fronteira da FFI e
trata a chamada como se ela retornasse NextWakeup::unchanged() — o worker
continua em execução.
Passe o parâmetro handle para SqlQueryCapability::open para
executar SQL de dentro do worker.
Consulta SQL
A capabilitysql_query abre uma sessão SQL a partir de um callback de
thread_worker, de modo que um worker em segundo plano pode executar instruções no servidor em que ele está
carregado. Declare-a junto com ThreadWorkerCapability e abra uma sessão
com o ThreadHandle que o worker recebe:
SqlQueryCapability::open(handle) retorna None se a capability não foi
populada (preview desligado ou não solicitada), se a ABI é antiga demais ou se o servidor
não conseguiu abrir uma sessão — verifique isso antes de usar o resultado.
Uma Session oferece duas maneiras de executar uma instrução:
execute(sql)armazena em buffer o conjunto de resultados completo e retorna umQueryResult. Chamenext_row()repetidamente até que ela retorneNone; cadaRowlê colunas comget_int(i),get_str(i),get_real(i)ouget_bytes(i).get_bytes/get_strretornamNoneparaNULLdo SQL ou um índice fora do intervalo (e também para bytes que não são UTF-8, no caso deget_str);get_int/get_realanalisam a coluna primeiro como texto, então também retornamNonepara texto que não pode ser analisado. O próprioexecuteretornaNoneapenas em falha de configuração (sem sessão, ou sem memória).for_each(sql, |row: Row<'_>| { ... })transmite as linhas para uma closure em vez de armazenar em buffer o conjunto de resultados completo. OQueryResultque ele retorna carrega apenas diagnósticos — sem linhas em buffer para iterar — e também retornaNoneem falha de configuração.
has_error() e error() (um Option<Diag> com errno,
severity, sqlstate e message) em qualquer um dos resultados antes de confiar que uma
instrução teve sucesso. warnings() retorna todos os avisos e notas anexados ao
resultado.
Uma Session e um QueryResult fecham, cada um, seu handle subjacente quando são
descartados — não há um método de fechamento para você chamar.
Acesso ao Keyring
A capabilitykeyring lê e escreve segredos armazenados no componente keyring
do MySQL — chaves de API, chaves de criptografia, qualquer coisa que não deveria
ficar em uma tabela. Um componente keyring (por exemplo, component_keyring_file) deve ser carregado
na inicialização do servidor por meio de um manifesto de componente e seu arquivo de configuração, conforme descrito em
Keyring Component Installation;
INSTALL COMPONENT não o torna disponível. Sem um, toda leitura e escrita falha com
KeyringError::NoComponent.
read(data_id, auth_id, buf) preenche o buffer que você passa e retorna
Ok(Some(n)) com o comprimento do segredo, ou Ok(None) quando não existe
nenhum segredo sob data_id — um resultado normal, não um erro. write(data_id, auth_id, data) retorna Ok(()) em caso de sucesso. auth_id é o usuário
proprietário; passe None para chaves internas não associadas a um usuário
específico.
Ambos retornam Err(KeyringError) em caso de falha: CapabilityUnavailable (a
capability nunca foi conectada), NoComponent (nenhum componente keyring no
servidor) ou Other.
O keyring não tem uma sondagem de tamanho: um segredo maior que o buffer que
você passa para read volta como Ok(None), indistinguível de uma chave
inexistente. Dimensione seu buffer para o maior segredo que você espera
armazenar.
Próximos Passos
Capabilities Preview (C++)
O índice completo de capabilities, o nível Preview e as capabilities
exclusivas do C++: auth, mysql_services, session_var, statement_event, as
capabilities de índice personalizado e armazenamento de coluna.
Referência da API Rust
InValue, VdfReturn, extension!, func! e custom_type! — todos os campos.