sexta-feira, 2 de outubro de 2026

Porque o Create é Fora do Try/Finally

Se você programa em Object Pascal (Delphi / Lazarus), com certeza já viu esse padrão de código:

qry := TZQuery.Create(nil);
try
  qry.Connection := ObterConexao;
  // operações no banco de dados...
finally
  qry.Free;
end;

Uma dúvida muito comum de quem está começando — e até de desenvolvedores mais experientes — é: "Por que a instanciação TZQuery.Create(...) é feita antes da instrução try e não dentro dela?"

A resposta envolve o funcionamento da gestão de memória e o tratamento de exceções no Pascal.

1. A Regra de Ouro do bloco try/finally

O objetivo da instrução try...finally é garantir a liberação de recursos (executando o bloco finally), independentemente de ter ocorrido uma exceção ou não dentro do bloco try.

💡 Princípio Fundamental:
Você só deve tentar liberar um recurso no bloco finally se esse recurso foi **efetivamente e com sucesso alocado** antes de entrar no bloco.

2. O que acontece se colocarmos o `.Create` DENTRO do `try`?

Considere a versão **incorreta** do código abaixo:

// ❌ CÓDIGO INCORRETO - EVITE ISSO!
try
  qry := TZQuery.Create(nil); // E se isto falhar?
  qry.Connection := ObterConexao;
finally
  qry.Free;
end;

Agora imagine o seguinte cenário de erro durante o processo de instanciação:

  1. O construtor TZQuery.Create começa a ser executado para alocar memória.
  2. Por algum motivo (como falta de memória no sistema ou falha na inicialização interna do componente), o método Create lança uma **exceção**.
  3. A variável qry fica com um valor indefinido (lixo de memória) ou nil, pois a atribuição qry := ... **não foi concluída**.
  4. Como o Create estava dentro do bloco try, a exceção força o fluxo da aplicação a pular **imediatamente** para o bloco finally.
  5. O bloco finally tenta executar qry.Free em uma variável que aponta para um ponteiro inválido ou não inicializado.
🔥 O Resultado: Access Violation!
Ao tentar executar qry.Free em um objeto que falhou ao ser criado, o sistema pode disparar um erro catastrófico de Access Violation (Violação de Acesso), mascarando o erro original da criação e tornando a depuração do problema muito mais difícil.

3. A Forma Correta e Segura

Ao manter o Create fora do bloco try, garantimos um fluxo limpo e robusto:

//  CÓDIGO CORRETO E SEGURO
qry := TZQuery.Create(nil);
try
  qry.Connection := ObterConexao;
  // Se ocorrer um erro aqui, a query já existe!
  // O finally vai destruí-la com segurança.
finally
  qry.Free;
end;

O que muda nesse cenário?

  • Se o .Create falhar: O fluxo nem sequer entra no bloco try. A exceção é capturada pela aplicação sem passar pelo finally, evitando tentar liberar algo que não existe.
  • Se o .Create for bem-sucedido: O objeto qry estará validado na memória. Em seguida, o fluxo entra no bloco try e, ocorrendo erro ou não nas operações seguintes (como conectar ao banco ou executar SQL), o finally garantirá o qry.Free com 100% de segurança.
📌 Dica sobre `Free` vs `FreeAndNil`:
O método .Free interno das classes do Delphi verifica se a referência é diferente de nil antes de chamar o destruidor. Portanto, chamar qry.Free é completamente seguro, desde que o objeto tenha sido devidamente instanciado.

Conclusão

Esta é uma boa prática para **qualquer objeto em Pascal** (e em várias outras linguagens com gerenciamento manual ou por blocos try/finally).

A regra simples para memorizar no seu dia a dia é: Aloque antes do try, proteja no try e libere no finally!

Guia para Instalação do Firebird no Linux

O Firebird é um sistema de gerenciamento de banco de dados relacional (RDBMS) de código aberto, leve, robusto e totalmente feature-complete (com todos os recursos). Sua arquitetura multi-geracional (MVCC) oferece excelente concorrência e alto desempenho para aplicações de todos os portes.

Este artigo detalha o passo a passo completo para realizar a instalação do Firebird a partir do pacote binário oficial em sistemas operacionais Linux, explicando os pré-requisitos, os cuidados essenciais com caminhos e os argumentos de linha de comando disponíveis.


1. ⬇️ Pré-requisitos e Download

Antes de iniciar a instalação no seu ambiente Linux, certifique-se de que você possui:

  • Privilégios administrativos: Acesso root ou permissões via sudo.
  • Pacote de instalação: O arquivo compactado para Linux x64 (formato .tar.gz) obtido diretamente no site oficial do Firebird.

2. 📂 Descompactação e Preparação

Após realizar o download do pacote, siga os passos abaixo no terminal para descompactá-lo:

  1. Navegue até o diretório onde o arquivo foi baixado (exemplo: ~/Downloads):
    cd ~/Downloads
  2. Descompacte o arquivo tar.gz (substitua pelo nome exato do arquivo baixado):
    tar -zxvf Firebird-5.0.3.1683-0-linux-x64.tar.gz
  3. Entre na pasta gerada pela descompactação:
    cd Firebird-5.0.3.1683-0-linux-x64/
⚠️️ Atenção importante (Espaços no caminho): Se a pasta onde o instalador está localizado contiver espaços em branco no nome (ex: /home/usuario/Downloads/Banco de Dados/...), o script padrão do instalador do Firebird poderá falhar com o erro "unexpected operator".

Para evitar isso, mude o instalador para um diretório sem espaços antes de executar (ex: /opt/Firebird_Installer/).

3. 🚀 Execução do Instalador (Script install.sh)

O Firebird fornece um script interativo chamado install.sh para gerenciar a instalação. Ele deve ser executado com privilégios de superusuário:

sudo ./install.sh

4. ⚙️ Argumentos de Linha de Comando (Modo Avançado / Silencioso)

Para cenários de automação, scripts de implantação ou para evitar as telas interativas, o script aceita argumentos de linha de comando:

Argumento Descrição Exemplo de Uso
-path <dir> Define o diretório customizado onde o Firebird será instalado (padrão: /opt/firebird/). -path /opt/Firebird/fb_5_0/
-silent Executa a instalação em modo silencioso (sem interações ou perguntas na tela). -silent
-service Configura automaticamente o Firebird como serviço do sistema para iniciar com o boot. -service
-nostart Instala o serviço, mas evita que ele seja iniciado imediatamente após o término. -nostart
-nolink Não cria links simbólicos globais no diretório /usr/bin/. -nolink

Exemplos práticos de execução:

  • Instalação Silenciosa Completa (Recomendada para servidores):
    sudo ./install.sh -silent -service
  • Instalação Silenciosa com Caminho Personalizado:
    sudo ./install.sh -path /opt/Firebird/fb_5_0_3_1683/ -silent -service

5. ✅ Pós-Instalação e Verificação

Após concluir a instalação, é fundamental verificar se o serviço está rodando corretamente e realizar os ajustes iniciais de segurança.

Verificar o status do serviço

Em distribuições Linux modernas que utilizam systemd (Ubuntu, Debian, Fedora, CentOS atualizados):

sudo systemctl status firebird

O status retornado deve ser active (running).

Testando a conexão com o ISQL

Você pode utilizar a ferramenta utilitária isql para testar o acesso ao banco de dados de segurança padrão:

/opt/firebird/bin/isql

No prompt interativo do utilitário, execute a conexão informando a senha padrão do usuário SYSDBA (que inicialmente é masterkey):

SQL> CONNECT 'localhost:/opt/firebird/security5.fdb' USER 'SYSDBA' PASSWORD 'masterkey';

Alterando a senha do SYSDBA (Essencial para Segurança)

Por motivos de segurança, altere imediatamente a senha padrão utilizando a ferramenta gsec:

sudo /opt/firebird/bin/gsec -database security5.fdb -user sysdba -password masterkey
GSEC> modify sysdba -pw SuaSenhaSuperSeguraAqui!
GSEC> quit

Pronto! Seu ambiente Firebird no Linux está instalado, configurado como serviço e pronto para receber suas bases de dados e aplicações.

domingo, 23 de agosto de 2026

Explicação sobre os "Donos de Objetos" em sua Criação

Tutorial rápido — Create(Owner) em Object Pascal

Em Object Pascal, muitos componentes, incluindo formulários, são criados utilizando o padrão:

```
Objeto := TClasse.Create(Owner);

O parâmetro Owner define o proprietário do componente. Uma das principais responsabilidades do Owner é controlar a destruição automática do objeto.

```

1. Create(Application)

Form2 := TForm2.Create(Application);

Nesse caso:

  • O Owner do formulário é Application.
  • A aplicação será responsável pela sua destruição.
  • O formulário também pode ser destruído antecipadamente usando Free.
Uso comum: formulários que permanecem vinculados ao ciclo de vida da aplicação.

2. Create(Self)

Form2 := TForm2.Create(Self);
Atenção: Self não significa simplesmente "ele mesmo". Em Object Pascal, Self representa a instância atual do objeto.

Por exemplo:

procedure TForm1.Abrir;
begin
  Form2 := TForm2.Create(Self);
end;

Nesse exemplo:

  • Self representa Form1.
  • Portanto, o Owner de Form2 será Form1.
  • Quando Form1 for destruído, Form2 também será destruído automaticamente.

3. Create(nil)

Form2 := TForm2.Create(nil);

Quando o parâmetro é nil, o formulário é criado sem Owner.

  • Nenhum outro objeto será responsável pela sua destruição.
  • O formulário não será destruído automaticamente por um Owner.
  • O código que criou o formulário deve cuidar de sua destruição.

Um padrão comum para um formulário modal é:

Form2 := TForm2.Create(nil);
try
  Form2.ShowModal;
finally
  Form2.Free;
end;
Importante: Create(nil) não significa "na prática, Application". Se o Owner é nil, o objeto realmente não possui proprietário.

4. Application.CreateForm

Application.CreateForm(TForm2, Form2);

CreateForm é um método de TApplication usado para criar formulários.

Conceitualmente, o resultado é semelhante a criar o formulário passando Application como Owner:

Form2 := TForm2.Create(Application);

Portanto, nesse caso, o formulário fica associado ao ciclo de vida da aplicação.

Regra prática

Criação Owner Responsável pela destruição
Create(Application) Application Application
Create(Self) Objeto representado por Self Objeto representado por Self
Create(nil) Nenhum Seu código

Owner não é Parent

Um conceito importante é não confundir Owner com Parent.

Owner

Está relacionado ao gerenciamento do ciclo de vida e destruição dos componentes.

Parent

Está relacionado à hierarquia visual dos controles.

Por exemplo:

Button1.Parent := Panel1;

Nesse caso, Panel1 passa a ser o Parent visual do botão. Isso não significa que Panel1 tenha se tornado automaticamente o Owner do botão.

Resumo

```
  • Owner controla quem será responsável pela destruição automática do componente.
  • Self representa a instância atual do objeto.
  • nil significa que o objeto não possui Owner.
  • Create(nil) não transforma o Owner em Application.
  • Owner e Parent são conceitos diferentes.

A escolha do Owner deve levar em consideração quem deverá controlar o ciclo de vida do objeto criado.

```

Abraços

Terence

sexta-feira, 21 de agosto de 2026

Placa Mãe Gigabyte com Ryzen 5300G, não exibe imagem no boot inicial com cabo HDMI

Recentemente passei por um problema bastante intrigante ao montar e configurar um setup com uma placa-mãe Gigabyte A520M, processador AMD Ryzen 3 5300G (com vídeo integrado Radeon) e um monitor da marca Aitek.

Ao conectar o computador através do cabo HDMI, as imagens iniciais do sistema — como a tela da BIOS/Setup e a logo de carregamento do sistema operacional — simplesmente não apareciam. O monitor ficava sem sinal ou em tela preta e o vídeo só dava ar da sua graça quando o sistema operacional alcançava a tela de Login.

Por outro lado, ao utilizar um cabo VGA analógico antigo, o vídeo funcionava perfeitamente desde o primeiro segundo ao ligar a máquina.

Daria para usar no VGA? Sim, mas...

Seria perfeitamente possível continuar utilizando o cabo VGA. No entanto, o cabo VGA utiliza sinal analógico, o que sujeita a imagem a interferências e limita a fidelidade de cores e nitidez em monitores modernos. Como o objetivo era utilizar a transmissão digital e de melhor qualidade do HDMI, fui atrás da solução.

A Solução: Desabilitar o CSM no BIOS

A raiz do problema estava no modo de legado da placa-mãe. Para resolver o problema definitivamente e ter imagem via HDMI desde o momento em que o botão Power é pressionado, siga o passo a passo:

1. Conecte o cabo VGA temporariamente

Ligue o computador utilizando o cabo VGA para que você consiga visualizar a tela de inicialização e acessar o setup da placa-mãe.

2. Acessar o BIOS do sistema

Ao ligar a máquina, pressione repetidamente a tecla Delete (ou Del) para acessar a BIOS da placa-mãe Gigabyte.

3. Localize a opção de Boot e altere o CSM

Na minha placa, dentro do BIOS, ir até a aba Boot. Procurar pela opção CSM Support (poderia ser Compatibility Support Module) e alterar seu status para Disabled (Desabilitado).

4. Salvar e trocar os cabos

Pressione a tecla F10 para salvar as alterações e sair da BIOS. Desligue o computador, desconecte o cabo VGA, conecte o cabo HDMI e ligue a máquina novamente.

Voilà! A imagem da logo da Gigabyte e da BIOS passou a exibir normalmente via HDMI desde o primeiro segundo.

Por que isso acontece?

💡 Entendendo a parte técnica (UEFI vs CSM - explicação dada pela IA do Google):
O CSM (Compatibility Support Module) é um componente do firmware da placa-mãe que emula o antigo sistema BIOS (Legacy) para manter compatibilidade com sistemas operacionais e placas mais antigas.

Ao desabilitar o CSM, a placa-mãe é forçada a rodar em modo UEFI puro. Nesse modo, a firmware carrega nativamente os drivers gráficos digitais UEFI (GOP - Graphics Output Protocol), inicializando saídas de vídeo digitais de alta resolução (como HDMI e DisplayPort) imediatamente no boot, sem depender das rotinas analógicas legadas (VGA).
⚠️ Atenção antes de desabilitar o CSM:
Para que o sistema operacional inicie corretamente em modo UEFI puro (com CSM desabilitado), o seu disco de boot (SSD/HD) precisa estar formatado no esquema de partição GPT. Se o disco estiver no formato antigo MBR, o sistema não vai encontrar o boot até que a tabela de partição seja convertida.

Conclusão

Se você está enfrentando tela preta na inicialização ao usar saídas digitais em processadores Ryzen com vídeo integrado ou placas de vídeo modernas, verificar o estado do suporte a CSM na BIOS é o primeiro passo. É uma configuração simples que garante o funcionamento correto das conexões digitais modernas.

Espero ter ajudado.

Abraços a todos

quinta-feira, 30 de julho de 2026

Importância da escolha do Character Set e Collation no Firebird e MariaDB

Um dos erros mais comuns e com maior potencial de dor de cabeça na modelagem de um banco de dados é negligenciar a escolha do Character Set e do Collation no momento de sua criação. Ajustar isso tardiamente em um banco de produção exige migrações complexas, reindexação de tabelas e pode quebrar consultas já existentes.

Neste artigo, vamos entender a fundo o papel de cada um desses conceitos e ver como configurá-los corretamente no Firebird e no MariaDB.

1. Desmistificando: Character Set vs. Collation

💡 Em resumo:
• Character Set (Conjunto de Caracteres): Determina quais símbolos e letras o banco é capaz de armazenar e quantos bytes cada caractere consome.
• Collation (Colação / Ordenação): Determina como esses caracteres são comparados, ordenados e pesquisados em cláusulas como WHERE, ORDER BY e GROUP BY.

O Character Set (Armazenamento)

Cada caractere armazenado precisa ser traduzido em bytes no disco. Se você escolher um conjunto limitado como o ASCII clássico, não conseguirá guardar acentos (á, ç, õ). Se escolher ISO8859_1 ou WIN1252 (comuns em legado), conseguirá armazenar o português, mas falhará ao tentar salvar símbolos em grego, cirílico ou emojis.

Atualmente, o padrão recomendado mundialmente é o UTF-8 (no MariaDB/MySQL conhecido como utf8mb4 e no Firebird como UTF8), pois ele aceita qualquer caractere do planeta.

O Collation (Regras de Comparação)

O Collation define o comportamento do banco em buscas de texto. Por exemplo:

  • Jose é igual a jose? (Diferenciação de Maiúsculas/Minúsculas)
  • Jose é igual a José? (Diferenciação de Acentuação)

No MariaDB e em outros bancos relacionais, os nomes das collations frequentemente trazem sufixos que explicam esse comportamento:

  • _ci (Case Insensitive): Não diferencia maiúsculas de minúsculas. Ex: 'MARIA' = 'maria'.
  • _cs (Case Sensitive): Diferencia maiúsculas de minúsculas. Ex: 'MARIA' ≠ 'maria'.
  • _ai (Accent Insensitive): Não diferencia acentos. Ex: 'João' = 'Joao'.
  • _bin (Binary): Compara byte a byte estritamente (máximo desempenho, mas diferencia tudo).

2. Definição em Níveis de Hierarquia

Tanto no MariaDB quanto no Firebird, você pode definir essas configurações em três níveis:

  1. Nível de Banco de Dados: O padrão herdado por novas tabelas.
  2. Nível de Tabela: O padrão para os campos daquela tabela específica.
  3. Nível de Coluna: Substitui a regra da tabela para um campo individual (útil para chaves de integração, hashes MD5/SHA, etc.).

3. Exemplos Práticos no MariaDB

Criação do Banco de Dados

Recomendado para suporte completo a Unicode e emojis no MariaDB:

CREATE DATABASE sistema_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

Tabela com Exceção na Coluna

Note como a coluna hash_senha utiliza um collation binário para comparações exatas e performance:

CREATE TABLE usuarios (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nome VARCHAR(100), -- Herda utf8mb4 / utf8mb4_unicode_ci do banco
  codigo_iso VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_cs,
  hash_senha VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
) ENGINE=InnoDB;

4. Exemplos Práticos no Firebird

Criação do Banco de Dados

Para suporte a acentuação do português do Brasil com compatibilidade UTF-8:

-- Opção com UTF8 (Moderna e recomendada)
CREATE DATABASE '/caminho/banco.fdb'
  DEFAULT CHARACTER SET UTF8
  COLLATION PT_BR;

-- Opção legada em ISO8859_1 (Caso utilize sistemas legados como Delphi antigo/VCL)
CREATE DATABASE '/caminho/banco_legado.fdb'
  DEFAULT CHARACTER SET ISO8859_1
  COLLATION PT_BR;

Tabela com Coluna Customizada

CREATE TABLE CLIENTES (
  ID INT NOT NULL PRIMARY KEY,
  NOME VARCHAR(100), -- Herda do banco
  SIGLA_ESTADO VARCHAR(2) CHARACTER SET WIN1252
);

5. O Impacto Direto no Desempenho e Armazenamento

A escolha incorreta pode afetar a saúde e o tempo de resposta do servidor de banco de dados:

Fator Single-Byte (ex: ISO8859_1 / Latin1) Multi-Byte (ex: UTF-8 / utf8mb4)
Espaço em Disco 1 byte por caractere fixo. 1 a 4 bytes por caractere (variável).
Uso de Memória/Índices Menor consumo em índices de texto. Índices ocupam mais espaço na RAM e em disco.
Indexação Mais simples de calcular ordens. Regras complexas de ordenação exigem mais CPU.
Compatibilidade Limitada a regiões geográficas. Universal (Sistemas Web, APIs REST, JSON).
⚠️ Cuidado com conversões implícitas (Cast):
Fazer um JOIN entre duas tabelas onde as colunas envolvidas possuem Character Sets ou Collations diferentes faz com que o banco de dados ignore os índices e realize a conversão em memória para cada linha lida (type coercion), o que pode deixar consultas centenas de vezes mais lentas.

Conclusão

Para novas aplicações web e desktop modernas, prefira sempre o padrão UTF-8 (com utf8mb4 no MariaDB e UTF8 no Firebird) utilizando collations insensíveis a maiúsculas/acentos para campos de busca de usuários (como PT_BR ou unicode_ci). Guardar dados com o charset adequado garante a integridade da sua informação e evita gargalos de desempenho difíceis de rastrear no futuro.