vsql_allow_preview_extensions = ON para instalar
(consulte Habilitando o Nível Preview) — as
extensões que não usam capabilities Preview instalam normalmente,
independentemente dessa configuração.
Habilitando o Nível Preview
Definavsql_allow_preview_extensions = ON com SET PERSIST antes de instalar
qualquer extensão que use uma capability Preview:
SET GLOBAL é rejeitado para essa variável — o servidor requer SET PERSIST
para que a configuração sobreviva à reinicialização. As extensões com
capabilities Preview são carregadas na inicialização, então a variável deve
estar configurada como ON quando o servidor iniciar.
Se você estiver iniciando o mysqld diretamente (por exemplo, a partir de um
script de instalação que inicia o servidor pela primeira vez), passe a flag na
linha de comando — o mysqld-auto.cnf ainda não existirá para carregar o valor
persistido:
Índice de Capabilities
Padrão de Registro
Para usar uma capability Preview, declare um objeto de capability por valor no escopo do arquivo e passe-o por referência para.with() dentro de
make_extension(). O servidor popula o pointer abi do objeto durante o
registro:
.with(capability) informa ao servidor quais capabilities a extensão requer. Se
vsql_allow_preview_extensions estiver em OFF quando a extensão for instalada, o
servidor rejeita a instalação com um erro que nomeia a capability.
Acesso ao Keyring
A capability keyring (vsql::preview::keyring) permite que as extensões leiam e
escrevam segredos armazenados no componente keyring do MySQL. As extensões a
usam para coisas como chaves de API, chaves de criptografia ou outros segredos
que não deveriam ficar em tabelas SQL.
O nome da capability VEF_PREVIEW_KEYRING_NAME é "vsql::preview::keyring".
Um componente keyring deve estar instalado no servidor MySQL para que leituras e
escritas tenham sucesso. Sem um, as operações retornam
KeyringCapability::Status::UNAVAILABLE.
Valores de Status
KeyringCapability::Status é um enum com escopo retornado por read() (dentro
de ReadResult) e por write():
Declarando a Capability
Inclua o cabeçalho, declare um objeto de capability no escopo do arquivo e passe-o para.with():
g_keyring é populado pelo servidor no momento do carregamento. Os
métodos read() e write() retornam Status::UNAVAILABLE em tempo de execução
quando nenhum componente keyring está instalado — verifique esse status em cada
chamada em vez de depender de uma verificação de disponibilidade separada.
Lendo e Escrevendo
data_id é o identificador da chave. auth_id é o usuário proprietário — passe
uma string vazia (ou omita-o em read, que assume {} como padrão) para ler ou
escrever chaves internas não associadas a um usuário específico.
read retorna um ReadResult por valor. Vincule-o com structured bindings:
Status::OK, value fica vazio.
write retorna Status diretamente e armazena data sob data_id /
auth_id.
Exemplo Completo
Esta é uma versão simplificada da extensão de testevsql_keyring_reader que é
distribuída com o servidor. Ela registra 2 VDFs: keyring_read e
keyring_store.
Variáveis de Status
A capability status_var (vsql::preview::status_var) permite que uma extensão
exponha contadores long long e double como variáveis de status do MySQL. A
extensão é dona do armazenamento e escreve nele; o servidor lê através dos
pointers cada vez que a variável de status é consultada.
Construa a capability com vsql::preview_status_var::make_capability(), passando
uma lista entre chaves de descritores de make_int(name, value_ptr) ou
make_double(name, value_ptr). O template deduz a contagem a partir da lista
entre chaves, então nenhum tamanho explícito é necessário.
Exemplo Completo
make_int requer um long long *; make_double requer um double *. Esses são
os únicos dois tipos compatíveis.
Acessando a partir do SQL
ApósINSTALL EXTENSION my_ext, a variável fica visível com o nome da extensão
como prefixo:
++
não-atômico podem ocasionalmente ser perdidos; isso é aceitável para contadores
aproximados de chamadas expostos via SHOW STATUS.
Variáveis de Sistema
A capability sys_var (vsql::preview::sys_var) permite que uma extensão registre
variáveis de sistema do MySQL respaldadas por armazenamento de propriedade da
extensão. Há suporte para três tipos: BOOL (bool *), INT
(long long *) e STR (char **). Os descritores INT também carregam limites
min_val e max_val; todos os descritores carregam um valor padrão e um
comentário.
Construa a capability com vsql::preview_sys_var::make_capability() e as funções
de fábrica correspondentes make_bool, make_int e make_str. O objeto de
capability também expõe get() e set() para acesso programático a partir do
código da extensão. Ambos retornam false em caso de sucesso.
Para reagir a mudanças de valor, encadeie .on_change<&fn>() em um descritor. O
callback recebe um sv::SysVarChange com var_name() e acessadores tipados
(as_int(), as_real(), as_str()).
O objeto de capability deve ter duração de armazenamento estática. O MySQL
escreve diretamente nos pointers de armazenamento quando o usuário define uma
variável.
Exemplo Completo
Acessando a partir do SQL
ApósINSTALL EXTENSION my_ext, as variáveis ficam acessíveis usando o nome da
extensão como prefixo de componente:
Lendo e Escrevendo a partir do Código da Extensão
Para variáveis INT e BOOL, leia o pointer de armazenamento global diretamente — o MySQL atualiza esses valores atomicamente. Para atualizar uma variável através do MySQL (de forma que travamento, validação de intervalo e persistência sejam tratados pelo servidor), chameSYS_VARS.set(extension_name, var_name, scope, value). Tanto set quanto get
retornam false em caso de sucesso.
scope controla a persistência:
Thread de Trabalho
A capability thread worker (vsql::preview::thread_worker) permite que uma
extensão execute uma thread em segundo plano conduzida pelo servidor. A thread é
iniciada e parada através de uma variável de sistema de controle que o servidor
registra no carregamento da extensão; o servidor invoca a função de trabalho da
extensão em um temporizador periódico, na prontidão de um descritor de arquivo,
ou em resposta a eventos de habilitação/desabilitação.
O nome da capability VEF_PREVIEW_THREAD_WORKER_NAME é
"vsql::preview::thread_worker".
Declarando a Capability
Inclua o cabeçalho, declare umThreadWorkerCapability instanciado sobre a sua
função de trabalho no escopo do arquivo e passe-o para .with():
ThreadWorkerCapability<&my_work>), portanto deve ser uma função com a
assinatura mostrada abaixo. O primeiro argumento do construtor é o sufixo do nome
da thread; o segundo argumento, opcional, sobrescreve o nome da variável de
sistema de controle.
Assinatura da Função de Trabalho
reason indica por que o servidor chamou a função. thread é o handle de
propriedade do servidor para este worker (NULL na chamada inicial de
VEF_WAKEUP_ENABLE — veja abaixo). arg é o pointer opaco registrado no
descritor; ele é repassado inalterado.
Ciclo de Vida do Wakeup
O servidor chama a função de trabalho com um de quatro motivos:
O parâmetro
thread é NULL quando o motivo é VEF_WAKEUP_ENABLE, porque o
handle da thread ainda não existe nesse ponto. Para os outros três motivos,
thread é não-nulo.
Valor de Retorno do Wakeup
vef_next_wakeup_t para atualizar a configuração
do próximo wakeup. Um valor zero em qualquer um dos campos significa “manter a
configuração atual” — retorne uma struct inicializada por valor (return {};)
para deixar ambos inalterados.
Para definir um novo descritor de arquivo de poll, retorne seu valor (deve ser
maior que zero). Para limpar um descritor de arquivo de poll existente, retorne
-1 em poll_fd.
O valor de retorno é ignorado quando o motivo é VEF_WAKEUP_DISABLE.
Nome da Thread e Variável de Controle
Dois campos no descritor controlam a nomenclatura:suffix— o sufixo do nome da thread. O servidor antepõe o nome da extensão, produzindo nomes de thread comomy_ext/monitor.var_name— opcional. Quando não-nulo, o servidor registra exatamente este nome como a variável de sistema de controle. Quando nulo, o servidor usa o padrão{suffix}_enabled.
SET GLOBAL {suffix}_enabled = ON; defina-a como OFF
para pará-lo.
Exemplo Completo
Uma extensão mínima com um único worker periódico que incrementa um contador de heartbeat a cada tique do temporizador.vsql_allow_preview_extensions = ON), o servidor
registra uma variável de sistema heartbeat_enabled. Habilite o worker com:
Consulta SQL
A capability sql_query (vsql::preview::sql_query) permite que uma extensão
execute instruções SQL a partir de uma thread em segundo plano. As consultas são
executadas dentro do servidor através da vtable da capability — as extensões não
são vinculadas a nenhuma biblioteca cliente do MySQL.
O nome da capability VEF_PREVIEW_SQL_QUERY_NAME é
"vsql::preview::sql_query".
Declarando a Capability
Inclua o cabeçalho, declare umSqlQueryCapability no escopo do arquivo e
passe-o para .with(). Ele é tipicamente registrado junto de um
ThreadWorkerCapability, já que as sessões são abertas a partir do callback do
worker:
g_sql.open(handle) retorna uma Session. Verifique-a com operator bool antes
de usá-la; uma Session inválida indica que a vtable da capability não foi
vinculada ou que o servidor não conseguiu alocar uma sessão. A Session é
move-only e se fecha na destruição.
Executando Consultas
UmaSession produz uma SqlQuery via session.sql(sv). A consulta pode ser
executada em dois modos:
execute()— executa a instrução e armazena em buffer todo o conjunto de resultados em umResult. Itere as linhas chamandonext()no ritmo do chamador.for_each(fn)— executa a instrução e invocafnuma vez por linha à medida que as linhas são produzidas, sem armazenar em buffer. OResultretornado carrega apenas diagnósticos (nenhuma linha).
Result. Um Result não-nulo não significa que a instrução
teve sucesso — chame has_error() para descobrir.
Em buffer (execute):
column_str() retorna um string_view que é válido apenas até a próxima chamada
de next() ou até que o Result seja destruído. Copie-o se um tempo de vida
mais longo for necessário. Um string_view com data() == nullptr indica SQL
NULL.
Em streaming (for_each):
Row passada para o callback é válida apenas durante a chamada — não armazene
referências a ela entre as linhas. O Result retornado por for_each não contém
linhas em buffer; next() nele não produzirá dados. Use-o apenas para
has_error(), error(), warning_count() e warning(i).
Diagnósticos
Tantoexecute() quanto for_each() expõem diagnósticos através do Result
retornado. Um diagnóstico é um Diag:
Result expõe:
error() retorna um Diag construído por padrão (errno_ == 0) quando a
instrução teve sucesso. warning(i) retorna um Diag construído por padrão
quando i >= warning_count().
Os views sqlstate e message apontam para armazenamento de propriedade do
Result e se tornam inválidos quando o Result é destruído — copie-os se eles
precisarem sobreviver a ele.
Exemplo Completo
Um worker que executa uma consulta em buffer e uma consulta em streaming a cada tique, registrando diagnósticos de ambas:Armazenamento de Colunas
O column storage permite que uma extensão registre um layout binário personalizado em disco diretamente com o InnoDB para um de seus tipos personalizados, em vez de rotear os bytes do tipo através do payload VARBINARY da linha. Use-o quando o seu tipo precisa de um formato em disco que o VARBINARY não consegue expressar — por exemplo, um array compactado de floats que precisa residir em páginas dedicadas. Este é um recurso de capability: ele habilita novos layouts de armazenamento, não é um botão de ajuste para os existentes.Declarando as Capabilities
Duas capabilities Preview trabalham juntas:vsql::preview::storage— abre acesso à infraestrutura de armazenamento do InnoDB (mini-transações, segmentos, páginas). Declare umaStorageCapabilityno escopo do arquivo.vsql::preview::column_store— vincula uma implementação de armazenamento por tipo a um dos tipos personalizados da extensão. Declare umaColumnStoreCapabilityno escopo do arquivo usandomake_column_store<Ctx>(TYPE).…build().
.with() em make_extension():
make_column_store<MyCtx>(MY_TYPE) liga a implementação a um tipo personalizado
registrado na mesma extensão. Todos os sete slots são obrigatórios no momento do
build(), porque cada um mapeia para um ponto distinto no ciclo de vida da
coluna que o InnoDB alcançará durante a operação normal.
As Sete Funções de Armazenamento
Toda função recebestorage::Column::StorageCtx<MyCtx>*, cujo acessador user()
retorna o estado por coluna da extensão e cujo arena() fornece alocação
gerenciada pelo servidor para objetos auxiliares. Toda função retorna false em
caso de sucesso e true em caso de erro, escrevendo uma mensagem em error_msg
(capacidade error_msg_len) para que as falhas apareçam ao cliente SQL.
mark_delete e purge são distintos porque o MVCC do InnoDB requer que as
linhas excluídas permaneçam legíveis por snapshots mais antigos até que o purge
seja executado.
Contexto por Coluna e a Arena
O SDK C++ constróiMyCtx por padrão antes de chamar create ou load —
ctx->user() já está populado quando a sua função é acionada. MyCtx deve ser
construível por padrão; o SDK C++ chama T() sem argumentos.
Use ctx->user() diretamente para inicializar o estado. Não chame
ctx->arena().construct<MyCtx>() — isso aloca uma segunda instância não utilizada
e ctx->user() não aponta para ela.
load segue o mesmo padrão — ctx->user() é pré-populado e storage_ref carrega
o valor compactado armazenado por ctx->set_ref() em create:
ctx->arena() apenas para alocar objetos auxiliares que são grandes demais ou
dinâmicos demais para embutir diretamente em MyCtx. O SDK C++ destrói a arena
(e chama ~MyCtx()) automaticamente após o retorno de drop, independentemente
de drop ter sucesso.
Utilitários de Acesso ao InnoDB
Inclua<villagesql/preview/storage_api.h> para os primitivos do InnoDB. Todas as
leituras e escritas de página devem ocorrer dentro de uma mini-transação:
create — veja os exemplos de
create e load em Contexto por Coluna acima para o padrão completo de
configuração. Durante as operações DML, obtenha uma referência de segmento a
partir da página raiz para alocar novas páginas:
mtr_ref para as chamadas de escrita para que o InnoDB registre a mudança:
Ler ou escrever dentro das regiões de cabeçalho ou trailer corrompe a página — o
InnoDB usa esses intervalos de bytes para sua própria contabilidade e checksum.
Eventos de Instrução
A capability statement event (vsql::preview::statement_event) executa um handler
fornecido pela extensão após cada consulta terminar de executar. O servidor invoca
o handler sincronamente na própria thread da consulta e passa metadados de
execução — o texto da consulta, tempo, contagens de linhas, identidade da conexão
e indicadores de qualidade do otimizador. Use-o para registro de consultas lentas,
auditoria ou coleta de métricas.
O nome da capability VEF_PREVIEW_STATEMENT_EVENT_NAME é
"vsql::preview::statement_event".
Declarando a Capability
Declare umStatementEventCapability, instanciado sobre a fase de disparo e a sua
função handler, no escopo do arquivo e passe-o para .with():
vef_statement_event_phase_t. VEF_STATEMENT_EVENT_POSTEXECUTE dispara após uma
consulta terminar de executar, em caso de sucesso ou falha, e é a única fase
implementada nesta versão. Os outros valores de vef_statement_event_phase_t são
reservados; declarar um handler para um deles faz o servidor rejeitar o
INSTALL EXTENSION.
Argumentos do Handler
StatementEventArgs é um view somente leitura da consulta concluída; na fase
POSTEXECUTE todos os campos estão populados. Acessadores selecionados:
Como
query() retorna a forma reescrita do servidor quando existe uma, as
instruções que carregam credenciais chegam com o segredo ofuscado em vez de em
texto claro, correspondendo à forma como os logs geral, lento e binário já os
redigem: SET PASSWORD, CREATE/ALTER USER ... IDENTIFIED BY,
CHANGE REPLICATION SOURCE ... SOURCE_PASSWORD e
CREATE SERVER ... OPTIONS(PASSWORD ...). As instruções sem regra de reescrita
são entregues literalmente.
Os acessadores de string como query(), sqlstate() e error_message() apontam
para armazenamento que é válido apenas durante a chamada do handler — copie os
bytes se você precisar deles depois que o handler retornar.
StatementEventResult::error_msg(fmt, ...) escreve uma mensagem formatada com
printf. Na fase POSTEXECUTE a mensagem é informativa: o servidor a registra, mas
não a propaga para o cliente.
Exemplo Completo
Uma forma condensada da extensão de testevsql_slow_query_log
que é distribuída com o servidor. Ela registra cada consulta cujo tempo de
execução excede um limiar, combinando a capability statement event com
variáveis de sistema para configuração em tempo de execução:

