Esse artigo faz parte da revista Clube Delphi edição 8. Clique aqui para ler todos os artigos desta edição


Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML. 

Interbase Components

IBTable, IBQuery, IBDataBase, IBTransaction e IBUpdateSQL.

 

Comforme prometido, estaremos sempre mostrando as novidades da nova versão do Delphi. Todo desenvolvedor Delphi, quando se depara com um upgrade na ferramenta, examina promeiramente a palheta de componentes. E quantos componentes! O Delphi 5 trouxe nada mais do que 53 componentes novos! É claro que as novidades não limitam-se apenas a isto. O Delphi 5 também acrescentou comandos a sua sintaxe, novos Wizards, entre outros incrementos. Esta série começará por um assunto que, acredito, irá lhe agradar. Por dois motivos: primeiro, o fato de falar sobre banco de dados. Segundo, por se tratar do Interbase, o queridinho da Borland. Sim, parece que finalmente a Borland está dando a devida atenção ao seu SGBD. O Delphi, a partir de agora, possui uma interação íntima com o Interbase, ou seja, acessa diretamente este banco. Sem a necessidade do BDE.

O fato de a Borland começar a divulgar mais o Interbase pode ajudar muito o produto. Existem desenvolvedores brasileiros que ainda nem conhecem, ou pelo menos, não sabem o objetivo, deste banco de dados. Com o advento da paleta Interbase Components, muitos destes desenvolvedores irão explorar mais o banco e conhecê-lo melhor. O site oficial do Interbase também já está no ar, o que conta muitos pontos para quem vai precisar de maiores informações sobre o mesmo. Para conferir, visite em http://www.interbase.com.br.

Para quem está começando no assunto, vamos uma pequena introdução: O Interbase é um banco de dados relacional da Borland. Diferencia-se (e muito), do Paradox. Principalmente pelo fato de ser realmente um banco de dados, em contrapartida ao Paradox. Sim, pois o Interbase é um programa, que permanece em execução no servidor, controlando todas as requisições aos dados. Já no Paradox, não existe programa gerenciador, todos os clientes são responsáveis pela leitura/escrita dos dados, causando um efeito “cada um por si” na rede. Veja no gráfico abaixo:

 

 

A utilização de um programa controlando o acesso aos dados proporciona inúmeras vantagens durante o desenvolvimento de um projeto. Vejamos alguns:

 

1) O processamento das informações torna-se muito mais rápido. Ao utilizar o paradox, quando um filtro é realizado, este é processado na máquina cliente. O cliente recupera toda a tabela e realiza o filtro localmente. Já no Interbase, apenas os dados filtrados serão transportados para o cliente, já que o responsável pela realização do filtro é o servidor, e não o cliente.

 

2) O permissionamento de usuários é muito mais seguro. Isto porque os dados só podem ser acessados quando o Interbase Server está aberto, e este irá controlar a leitura/escrita dos dados de acordo com a senha de cada usuário. No paradox, em contrapartida, qualquer um pode abrir o arquivo, sem a necessidade de nenhum sistema gerenciador.

 

3) A integridade dos dados é realmente implementada no próprio Interbase. No Paradox, não é possível a utilização de recursos como integridade de deleção em cascata, integridade entre vários, entre outros. Tudo isto é possível no Interbase, facilitando muito a vida do desenvolvedor, visto que o mesmo não precisa estabelecer o controle de integridade relacional na parte cliente do sistema. Além de facilitar a manutenção do sistema, diminui a probabilidade de erro e elimina a possibilidade da integridade falhar.

 

4) O processamento de informações transacionais é mais seguro. O Interbase implementou o conceito real de transação, que garante a execução de um bloco de instruções com sucesso. Por exemplo, digamos que o sistema, em determinado momento, deve realizar três operações em seqüência: cadastrar a saída de material, retirar a quantidade do estoque, e marcar o pedido como entregue. E se o sistema falhar, antes de retirar a quantidade do estoque, ou de marcar o pedido como entregue? Inconsistências deste tipo podem ocorrer com freqüência em um sistema baseado em Paradox. Já com a utilização de transação do Interbase, o desenvolvedor poderia desenvolver a rotina da seguinte forma:

 

n Iniciar um bloco transacional (START TRANSACTION);

n Cadastrar Saída de material;

n Retirar Quantidade do Estoque;

n Marcar Pedido como Enfoque;

n Terminar o bloco transacional (COMMIT).

 

Portanto, o Interbase só irá efetivar as operações realizadas quando o comando Commit for executado. Caso alguma falha ocorra, o Interbase irá desconsiderar todas as atualizações realizadas desde o último comando Start Transaction realizado. Desta forma, o desenvolvedor pode garantir que tudo, ou nada, será efetuado, não havendo inconsistências.

O controle transacional do Interbase é possível graças ao seu gerenciador de logs. Toda instrução executada no banco é guardada em um arquivo interno de log, permitindo que o Interbase possa recuperar ou desfazer operações realizadas anteriormente, mesmo após um boot na máquina.

 

5) Outra vantagem deste banco é a distribuição da lógica da aplicação. O banco de dados permite armazenar procedures e funções dentro do SGBD. Estas funções, ao invés de serem executadas pelos clientes, serão apenas disparadas pelos mesmos. Vamos analisar os benefícios de possuir procedures armazenadas no servidor:

 

n O tráfego na rede é menor. Por exemplo, vejamos como um sistema Paradox se comportaria na realização do procedimento de entrega, citado anteriormente:

 

 

Com o Interbase, podemos ter uma procedure para retirar a quantidade do estoque e marcar o pedido como entregue. Veja no gráfico abaixo, como o tráfego na rede seria menor:

 

 

n O desenvolvimento do aplicativo torna-se menos trabalhoso. Como muita parte da lógica da aplicação irá residir no próprio servidor, a construção e manutenção do cliente será uma tarefa menos dispendiosa.

 

O Interbase oferece ainda muitos outros recursos, como Views, Otimização no uso de índices, Triggers (Eventos), entre outros. Esta matéria não tem o intuito de ser uma referência do Servidor Interbase, deixando esta tarefa para os manuais que acompanham o banco. Veremos agora toda a funcionalidade fornecida pelos objetos da paleta Interbase Components, uma das novidades do Delphi 5, que permitem a comunicação direta de um aplicativo Delphi com o banco Interbase.

 

Iniciando a conexão de um projeto com Banco:

Primeiramente, vamos criar a conexão do aplicativo com o Interbase. O objeto responsável pela conexão é o TIBDatabase. Como pode-se facilmente perceber, este objeto é muito semelhante ao já conhecido TDatabase, da palheta DataAccess. Crie um novo projeto no Delphi, e insira um objeto da classe TIBDatabase, no form.

Devemos configurar o objeto para que aponte para o nosso banco de dados. Para isto, dê um clique duplo sobre o objeto, para que a janela DataBase Component Editor seja exibida:

 

Figura 1. Janela de configuração do BD

 

O grupo Connection indica as informações para encontrar o banco de dados. Vamos iniciar conectando ao banco local, que é instalado juntamente com o Interbase Server. Selecione a opção Local. Em seguida, devemos indicar o nome do arquivo de banco de dados. Indique o caminho do banco de dados de exemplo: C:\Arquivos de programas\Borland\InterBase\examples\Database\employee.gdb

 

No Grupo Database Parameters, devemos preencher as informações de login. Na caixa UserName, digite SYSDBA, que é o username padrão criado no momento da instalação do Interbase. Este usuário tem o privilégio de administrador, e pode realizar todas as operações do banco. Na caixa password, digite masterkey, que é a senha padrão. A combo Character Set indica a linguagem de caracter utilizada para conexão com o banco. basta deixar em None. Desmarque também o CheckBox LoginPrompt. Com esta opção desmarcada, o objeto não irá pedir o nome e a senha do usuário toda vez que tentar efetuar a conexão com o banco (ao iniciar o aplicativo).

O segundo passo será inserir um objeto TIBTransaction. Este objeto, que  não possui equivalência na paleta DataAccess, representa a transação ativa no banco de dados. Ou seja, sempre irá existir uma transação aberta pelo usuário, mesmo que operações singulares estejam sendo realizadas. Após inserir o objeto TIBTransaction, configure sua propriedade DefaulDatabase, apontando-a para o objeto IBDatabase1. O procedimento inverso também deverá ser feito: selecione o objeto TIBDatabase e linke a propriedade DefaultTransaction com o objeto TIBTransaction. Após, os objetos deverão estar configurados de acordo com a tabela abaixo:

 

IBDatabase1

DatabaseName

C:\Arquivos de programas\Borland\InterBase\examples\Database

\employee.gdb

LoginPrompt

False

Params

user_names=SYSDBA

password=masterkey

Default

Transaction

IBTransaction1

 

IBDatabase1

DsfaultDatabase

IBDatabase1

 

E, para efetuar a conexão com o banco, basta alterar a propriedade Connected, do objeto IBDatabase1, e a propriedade Active, do objeto IBTransacrion1, ambas para True.

Repare que o objeto TIBTransaction possui outras propriedades sugestivas. A propriedade DefaltAction, em conjunto com a propriedade IdleTimer, permite definir ações automáticas para o objeto. Por exemplo, se definirmos defaultAction para UACommit, e indicarmos o tempo 10000 (milésimos de segundos) na propriedade IdleTimer, o objeto irá executar um Commit, automaticamente, a cada 10 segundos. Veja abaixo os possíveis valores para a propriedade DefaultAction:

 

TACommit: Confirma a execução das instruções enviadas, e fecha o handle de cursor aberto;

RACommitRetaining: Confirma a execução das instruções enviadas, mas permanece com o handle de transação aberto. Com esta opção, não será necessário abrir novamente a tabela após a confirmação das operações.

TARollback: Cancela a execução das instruções, e fecha o handle de cursor aberto. Após a execução deste comando, a tabela deverá ser reaberta.

TARollbackRetaining: Cancela a execução das instruções, mas permanece com o handle de transação aberto. Esta opção ainda não está disponível nas versões atuais do Interbase.

Vejamos a seguir como utilizar os demais componentes da paleta IB Components.

 

Trabalhando com um IBTable

O objeto IBTable representa um live result set, igualmente ao objeto Ttable da paleta DataAccess. Suas propriedades, eventos e métodos são muito parecidos e não haverá dificuldades de aprendizado para quem já conhece os objetos da paleta Data Access. Vamos criar um pequeno exemplo, uma DBGrid com um objeto TIBTable:

 

n Crie um novo form;

n Insira um objeto TIBDatabase, e linke-o com o banco de dados Employee.gdb;

n Insira um objeto TIBTransaction, e linke-o com o objeto IBDatabase1.

n Configure a propriedade DefaultTransaction, do componente IBDatabase, para IBTransaction1;

n Defina a propriedade Connected do objeto IBDatabase1, para True;

n Defina a propriedade Active, do objeto IBTransacrion, para True;

n Insira um objeto TIBTable no form;

n Selecione o objeto IBtable1 e defina na propriedade Database o objeto IBDataBase1. Repare que a propriedade Transaction será automaticamente definida, apontando para o objeto TIBTransaction1.

n Defina o nome da tabela na propriedade Tablename. Escolha a tabela CUSTOMER (clientes).

n Insira um objeto DataSource (Paleta DataAccess) no form. Configure sua propriedade DataSet para o objeto IBTable1.

n Insira um objeto IDBGrid no form e configure sua propriedade DataSource para o objeto DataSource1.

 

E finalmente, altere a propriedade Active, do objeto IbTable1, para True. Certamente os dados já serão exibidos na grade.

Repare que o ambiente de desenvolvimento do Delphi proporciona muita flexibilidade ao desenvolvedor. O objeto TdataSource e os objetos de visualização dos dados sempre serão os mesmos, não importa quem esteja fornecendo os dados. os objetos fornecedores podem ser DataAccess(BDE), ADO, Interbase, MIDAS, entre outros. A camada de interface permanecerá sempre intacta. É por esta e outras que o Delphi vem conquistando cada vez mais seu espaço no mercado de desenvolvimento mundial.

 

Nota: O uso do objeto TIBTable, apesar de não depender do BDE, é mais lento do que o objeto TIBQuery. Isto porque, assim como nos objetos Ttable e Tquery, o objeto TIBTable envia uma quantidade muito maior de instruções ao servidor, quando comparado ao objeto TIBquery. Para consultas, o objeto TIBquery será mais rápido. Para manutenção da tabela, o objeto TIBquery anexado ao objeto TIBUpdateSQL será mais rápido.

 

Trabalhando com Cached Updates no Objeto TIBTable

Vamos incrementar o nosso formulário de manutenção, e implementar o controle de Cached Updates em nosso objeto IBTable1. O conceito de Cached Updates, que já existe no objetos DataSet (Table/Query), permite a bufferização dos dados no lado cliente. Ou seja, as alterações não são enviadas diretamente ao servidor, permanecendo no buffer local, até que um único comando faça descarregar todo o pacote para o servidor. Isto causa um tráfego menor na rede, visto que as informações não serão enviadas a todo momento para o servidor. Nem sempre o uso de cached updates pode otimizar a performance do sistema, portanto, o seu uso não é uma obrigação.

Vamos iniciar inserindo dois botões:

 

Confirmar e Cancelar. Posicione-os de acordo com a figura abaixo:

 

 

Em seguida, altere a propiedade active do objeto IBTable1 para false e altere a propriedade para True. Isto irá colocar o objeto em modo CachedUpdate.
Preencha o evento OnClick dos botões de acordo com a listagem abaixo:

 

Botão Confirmar:

 

procedure TForm1.Button2Click(Sender: TObject);

begin

     IbTable1.ApplyUpdates;

end;

Botão Cancelar:

 

procedure TForm1.Button1Click(Sender: TObject);

begin

     Ibtable1.cancelUpdates;

end;

 

No botão confirmar, o método ApplyUpdates é o responsável por enviar as informações alteradas para o servidor. Já no botão cancelar, é executado o método Cancelupdates, para que os dados originais sejam resgatados. Ambos os métodos já estavam presentes no objeto Ttable.

 

Trabalhando com o Componente TIBQuery

Como já está bastante sugestivo, este objeto é o equivalente ao Tquery, da paleta DataAccess. Praticamente não houve alterações na forma de uso deste objeto. Vamos criar um pequeno exemplo:

 

n Insira um objeto IBDatabase e um IBTransaction, e linke os com o banco de dados Employee.gdb;

n Insira um objetoi TIBQuery e configure suas propriedades de acordo com a tabela abaixo:

 

IBQuery1

Database

IBDatabase1

SQL

Select *

from Customer

 

n Após, insira u objeto DataSource e linke-o ao objeto IBQuery1;

n Insira um objeto TDBGrid e linke-o ao DataSource;

n E, finalmente, configure a propriedade Active do objeto TIBQuery para True.

 

Conhecendo o Objeto TIBUpdateSQL

Mais um objeto já conhecido. O componente TIBUpdateSQL é equivalente ao componente TUpdateSQL da paleta DataAcess. Para quem não conhece, permita-me apresentá-lo: este objeto permite ao componente Tquery (neste caso, IBQuery) manipular dados da consulta, sem abrir um Live Result Set! Em uma situação normal, para que o objeto Query pudesse manipular os dados, o desenvolvedor deveria configurar sua propriedade RequestLive para True. Só que desta forma, a query estaria trabalhando como se fosse um objeto Ttable, e não haveria nenhum ganho de performance. Com o uso do objeto TUpdateSQL, o desenvolvedor pode simular um Live Result Set, utilizando comandos SQL que serão enviados ao servidor quando algum método Append, Edit ou Delete for executado. Vejamos um exemplo pratico:

Vamos aproveitar o formulário, que já possui um IBQuery. neste form, insira um objeto TDBNavigator, e linke-o ao objeto DataSource1. Insira também dois botões, e posicione-os de acordo com a figura.

 

 

Configure os objetos de acordo com a tabela a abaixo:

 

TABELA COM AS PROPRIEDADES DOS OBJETOS

DBNavigator1.dataSource

DataSource1

Button1.Caption

Confirmar

Button2.Caption

Cancelar

 

Neste exemplo, iremos controlar a transação manualmente, visto que não estaremos trabalhando com Cached Updates. Todas as alterações serão enviadas diretamente para o banco. Por isto, os botões Confirmar e Cancelar irão, respectivamente, efetuar um Commit e um RollBack no banco de dados. Vamos agora configurar o objeto IBUpdateSQL1:

Primeiramente, altere a propriedade UpdateObject, do objeto IBQuery, selecionando o objeto IBUpdateSQL1. Isto irá indicar que o objeto UpdateSQL será o encarregado de enviar as alterações realizadas através do objeto IBQuery1. Após, dê um clique duplo sobre o objeto IBUpdateSQL, para que a janela de configuração seja exibida:

 

 

Repare que a janela virá preenchida com os campos selecionados através do objeto IBQuery. Neste ponto, devemos indicar quais campos fazem parte da chave primária, e quais campos serão atualizáveis. Na lista KeyFields, selecione apenas o campo CUST_NO, que é a chave primária, e não será atualizada. Na lista UpdateFields, clique no campo CUSTOMER e selecione todos a partir deste. Estes são os campos que não fazem parte da chave, e poderão ser atualizados.

A seguir, basta clicar no botão Generate SQL, para que o objeto gere toda a cláusula SQL que será enviada ao banco, para cada tipo de atualização. Ao clicar neste botão, repare que a aba SQL será exibida:

O código SQL gerado deverá ser parecido com a listagem abaixo:

 

Alteração

update CUSTOMER

set

  CUSTOMER = :CUSTOMER,

  CONTACT_FIRST = :CONTACT_FIRST,

  CONTACT_LAST = :CONTACT_LAST,

  PHONE_NO = :PHONE_NO,

  ADDRESS_LINE1 = :ADDRESS_LINE1,

  ADDRESS_LINE2 = :ADDRESS_LINE2,

  CITY = :CITY,

  STATE_PROVINCE = :STATE_PROVINCE,

  COUNTRY = :COUNTRY,

  POSTAL_CODE = :POSTAL_CODE,

  ON_HOLD = :ON_HOLD

where

  CUST_NO = :OLD_CUST_NO

 

Inserção

 

insert into CUSTOMER

  (CUSTOMER, CONTACT_FIRST, CONTACT_LAST, PHONE_NO, ADDRESS_LINE1, ADDRESS_LINE2,

   CITY, STATE_PROVINCE, COUNTRY, POSTAL_CODE, ON_HOLD)

values

  (:CUSTOMER, :CONTACT_FIRST, :CONTACT_LAST, :PHONE_NO, :ADDRESS_LINE1,

   :ADDRESS_LINE2, :CITY, :STATE_PROVINCE, :COUNTRY, :POSTAL_CODE, :ON_HOLD)

 

Exclusão

 

delete from CUSTOMER

where

  CUST_NO = :OLD_CUST_NO

 

Repare que as variáveis precedidas de dois pontos(:), representam os valores originais da Query. Estas variáveis são setadas automaticamente pelo objeto, e o desenvolvedor não precisa se preocupar com a funcionalidade do mesmo. Está tudo pronto!

Devemos agora preencher os botões Confirmar e Cancelar. Veja abaixo o respectivo código dos botões:

 

procedure TForm1.Button1Click(Sender: TObject);

begin

    IBTransaction1.CommitRetaining;

end;

 

procedure TForm1.Button2Click(Sender: TObject);

begin

    IBTransaction1.Rollback;

    IBTransaction1.StartTransaction;

    IBQuery1.Open;

end;

 

No botão Confirmar possuímos apenas uma linha:

 

IBTransaction1.CommitRetaining;

 

O método CommitRetaining, envia o comando Commit ao servidor. A sua diferença para com o próprio método Commit, é que este retém o cursor aberto, não sendo necessário executar o método Open da Query novamente. Ao executar o método CommitRetaining, uma nova transação será aberta automaticamente.

Já no botão Cancelar, necessitamos de três linhas:

 

IBTransaction1.Rollback;

IBTransaction1.StartTransaction;

IBQuery1.Open;

 

O método Rollback irá cancelar todas as alterações efetuadas, porém, irá fechar o cursor da query. O método RoollbackRetaining, apesar de disponível, não é suportado pelas versões atuais do Interbase. O método Rollback também não inicia uma nova transação, e precisamos chamar explicitamente o método StarTransaction. Ao final, o método Open da query é executado, visto que a mesma será fechada pelo Roolback.

Basta agora executar e testar o projeto. Toda a funcionalidade de um formulário trabalhando com transações no Interbase, está pronto com apenas algumas linhas de código!

 

Conclusão

Nesta primeira parte da matéria, apenas os componentes básicos da paleta Interbase(IBTable, IBQuery, IBTransaction, IBDataBase e IBUpdateSQL) foram explorados. Na próxima edição, estaremos explorando os componentes IBDataSet, IBSQL, IBDatabaseInfo, IBSQLMonitor e IBEvents. Estes componentes fornecem uma funcionalidade própria do Interbase, e só existem devido a comunicação mais próxima que o delphi agora passa a ter com o banco. Os exemplos desta matéria estão disponíveis para download, no endereço http://www.clubedelphi.com.br/revista/edicao8/interbase.zip.