Repository navigation
internos dbware
mobius1qwe edited this page Oct 15, 2026
·
2 revisions
Home > Guia de contribuição > Internos: DBWare
Para quem mexe no código: módulo, pool de conexões, cache de SQL e os conectores FireDAC, Zeos e SQLdb. Aqui fica o porquê de cada parte ser como é, e o que não pode mudar sem quebrar algo. O código traz só a descrição curta de cada coisa.
Conteúdo da versão 2.0, ainda em desenvolvimento (branch 2.0).
-
Quem decide se a resposta vai no formato nativo é o link do cliente. O
TRALDBSQLCachechamaPrepareForDataSetcom o dataset que vai ler a resposta; oTRALStorageXMLLinkanota se é FireDAC, Zeos ouTBufDataset(pelo nome da classe, para não depender dos pacotes deles) e manda isso nas propriedades do storage. No servidor, oTRALDBModulepergunta ao storage (AllowNative) se aquele par cliente/driver aceita o nativo. Os outros links respondem como antes: nativo só com o mesmo driver. -
FireDAC grava e lê XML pelo MSXML, que é COM. A thread do servidor e um
programa console não iniciaram COM, e o FireDAC falha com "No active document".
RALDBFireDACeRALDBFiredacMemTablechamamCoInitializeExem volta dosfXML, e só desfazem o que eles fizeram. -
O fcl-db só lê
dfXML.dfXMLUTF8existe no enum e não tem leitor registrado, nem no FPC 3.3. O texto dodfXMLpassa pela codepage do sistema, que o RAL deixa em UTF-8 (LazUTF8), então os acentos sobrevivem. -
O nativo do sqldb abre a query com buffer.
TBufDataset.SaveToStreamnão funciona numa query unidirecional, e oOpenNativedo sqldb só serve à resposta nativa. OTRALDBBufDatasetcarrega a resposta nativa com as definições que vêm nela: as que ele adivinhou dogetsqlfieldssaem antes, como no memtable do FireDAC.
Na 1.x estas funções ficam em RALDBTypes; na 2.0 a unit é RALStorageTypes, e
RALDBTypes repassa para ela.
-
Dois valores viajam exatos. NUMERIC/DECIMAL (
ftBCD,ftFMTBcd) vão comosftBCD, com os dígitos em texto: como double,12345678901234.5678chegaria12345678901234.6fora do caminho nativo do FireDAC. E os milissegundos das datas vão no storage BSON (o kxBSON grava segundos inteiros) e no tempo Unix (dtfUnix, com decimais do segundo). Um leitor antigo não lê nenhum dos dois:RALLegacyWire := Truegrava o formato antigo para um lado cujos pares são mais velhos. A leitura aceita os dois formatos. -
O stream nativo carrega
FieldType, nãoRALFieldType(TRALDBInfoField.NativeDriver). Um cliente desse driver que monta os campos pelo schema (o Fields Editor monta) tem de usarFieldType, senão o campo não bate com o que carrega: um NUMERIC que o FireDAC leva comoftBCDpara a carga de umTFMTBCDField, e uma DATE lida por umTDateTimeFieldlevantaEConvertError. Servidor antigo não manda a chave: lê -1, e o cliente monta o que sempre montou. -
O tamanho diz se é data, hora ou os dois (
RALDateTimeKind):sftDateTimesozinho não diz. Amarrada como data e hora, uma hora chegaria numa coluna TIME do SQLite como'1899-12-30 hh:nn:ss.zzz', que nenhum driver lê de volta. Leitor antigo ignora o tamanho. -
As tabelas de nomes de tipo são preenchidas na
initialization, antes de qualquer thread, e depois só lidas.GetEnumNamepercorre a tabela RTTI e, no Delphi, devolve UTF-16 que ainda precisa virarStringRAL, por campo e por linha. As tabelas são preenchidas porGetEnumName, não à mão, porqueTFieldTypemuda de um compilador para outro. Preenchidas na primeira chamada, elas correriam entre threads: com 6 threads, 441 de 3000 rodadas deram nome errado ou exceção, e um''viraftUnknown, que o servidor recusa ("Field is of an unknown type") nos primeiros pedidos DAO paralelos. -
Enum que vem do fio se compara como
Cardinal. O Delphi compara um enum de até 128 membros como byte com sinal (Win32 e Win64), entãoOrd(x) > Ord(High(T))deixa passar de 128 a 255. Umcasetambém não salva: no Win32 o 128 cai no ramo desftShortInt, e no FPC o salto pela tabela docasedá access violation. Por isso todo valor do fio passa porRALIsFieldTypeOrdinalantes do cast. -
RALDBResponseErrorem três passos.AnswerExceptionresponde com um paramException, mas um param sozinho no corpo viaja sem nome (vira o corpo anônimo); param ausente é nil, então as leituras precisam de guarda (é o caminho de erro); e uma resposta só com status (um proxy, umAnswer(status)) não pode virar uma exceção de mensagem vazia. O status vai escrito na mensagem, para quem procura pelo número encontrá-lo.
Começar
Servidor
- Rotas e parâmetros
- Ler o pedido e responder
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- Swagger e Postman
- Servidor SOAP 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar