Expand description
DML em lote (batch) — o recurso “principal” de array DML do Firebird 4+.
Um Batch insere/atualiza/exclui muitas linhas com uma única instrução
preparada, acumulando mensagens no cliente e enviando-as ao servidor em uma
ida só. É muito mais rápido que executar a instrução linha a linha.
let mut batch = conn.create_batch(&tx, "INSERT INTO t (a, b) VALUES (?, ?)")?;
batch.add(&[Value::Int(1), Value::Text("um".into())])?;
batch.add(&[Value::Int(2), Value::Text("dois".into())])?;
let result = batch.execute(&mut conn, &tx)?; // envia + executa
println!("{} linhas afetadas no total", result.total_affected());
batch.close(&mut conn)?; // libera no servidor§Protocolo (FB4+, op codes 99–103)
Descoberto por captura de um cliente C usando a interface OO IBatch:
op_batch_create(99):stmt | blr(cstring) | msglen(u32) | pb(cstring). O BLR descreve o formato da mensagem (igual aoin_blrdeop_execute);msglené o tamanho do buffer de mensagem do lado do cliente.op_batch_msg(100):stmt | count(u32) | mensagens, cada mensagem no mesmo formato compacto (bitmap de nulos + valores XDR) usado emop_execute.op_batch_exec(101):stmt | transaction. Responde comop_batch_cs.op_batch_cs(103): estado de conclusão (contagens por linha + erros).op_batch_rls(102): libera o batch no servidor.
O cliente C agrupa create+msg e usa op_batch_sync (110) para drenar as
respostas adiadas; nós, sendo síncronos, lemos a resposta de cada op na hora.
§BLOBs em lote (política STREAM, op_batch_blob_stream 105)
Quando a instrução tem coluna BLOB, Connection::create_batch ativa a
política BLOB_STREAM no PB (TAG_BLOB_POLICY = 3). O chamador então usa
Batch::add_blob para registrar cada blob e recebe um id (quad) para pôr
no campo da linha. Em Batch::execute, antes das mensagens, enviamos:
op_batch_blob_stream (105): stmt | length(u32) | stream. O stream é a
concatenação CRUA (sem padding) dos blobs, cada um id(quad 8B BE) | size(4B BE) | bpb_size(4B BE) | bpb | dados. O length NÃO é o número de bytes no
wire: é o tamanho do buffer que o servidor aloca — a soma de align4(16 + bpb + dados) de cada blob — e deve ser múltiplo de 4 (o servidor rejeita
caso contrário). Ao percorrer o stream (ver xdr_blob_stream no servidor),
ele avança o ponteiro do buffer com alinhamento de 4 SEM consumir bytes do
wire para o padding; o laço termina quando o que resta é menor que um
cabeçalho (16 B) ou chega a zero. Por isso o wire carrega menos bytes que
length, e a próxima op pode começar em offset não múltiplo de 4.
Confirmado por captura do 11.batch.cpp (conteúdo 30 B → length 32; 33 B →
36) e pelo código do servidor. Os blobs vão antes das mensagens porque a
linha referencia o id já registrado.
op_batch_regblob (104): stmt | id_existente(quad 8B BE) | id_batch(quad).
Mapeia um BLOB já gravado fora do batch (Connection::write_blob) a um id
local, evitando reenviar os dados. Ver Batch::register_blob.
op_batch_set_bpb (106): stmt | bpb(cstring). Define o BPB padrão dos
blobs do batch; o servidor lê o isc_bpb_type para marcar os blobs como
segmentados ou stream. Ver Batch::set_default_bpb / Batch::set_segmented.
Em modo segmentado, cada segmento no stream é um u32 big-endian com o
comprimento seguido dos bytes, SEM padding; já o campo size do blob segue a
contabilidade do buffer do servidor (cabeçalho de 2 bytes alinhado a 2), ou
seja align2(2 + len). Capturado da Parte 3 do 11.batch.cpp.
Structs§
- Batch
- Um lote de mensagens vinculado a uma instrução preparada no servidor.
- Batch
Error - Um erro detalhado de uma mensagem específica do lote.
- Batch
Options - Opções de criação de um
Batch(clumplets doop_batch_create). - Batch
Result - Resultado da execução de um lote: o estado de conclusão por mensagem.