Páginas

domingo, 15 de maio de 2011

Lazarus - Acessando banco de dados com SQLdb - Parte III

Muita coisa mudou no Lazarus desde que começamos a dedicar este blog à divulgação deste poderoso IDE. Quando iniciamos usávamos a versão 0.9.28 e publicamos dois artigos voltados para o uso do conjunto de componentes SQLdb:

Lazarus - Acessando banco de dados com SQLdb - Parte I
Lazarus - Acessando banco de dados com SQLdb - Parte II

Hoje estamos com a versão 0.9.31. Neste post iremos apresentar algumas mudanças para melhor na utilização desses componentes.

Referências aos campos de uma tabela - criação de TFields

Para criar os TFields ainda é necessário que a TSQLQuery esteja ativa. Dê um duplo clique na TSQLQuery e você verá uma janela como esta:

Esta janela oferece uma barra de ferramentas bastante intuitiva. O botão adicionar irá abrir uma nova janela onde você poderá selecionar os campos da tabela que se deseja adicionar. Após selecionar os campos pressione o botão Create. O botão novo campo permite criar um campo de dado, calculado ou lookup. O uso desse botão irá abrir a seguinte janela:
Aqui você escolhe o tipo do campo em Field Type. Em Field properties podemos definir os valores das propriedades do campo. Depois confirme tudo pressionando Ok. Esteja sempre atento que as tabelas envolvidas na criação dos campos devem estar abertas.
Note também que esse procedimento irá criar variáveis do tipo TField, que podem ser usadas no código do nosso programa. Essas variáveis são criadas abaixo do Data Module conforme podemos ver na figura:

A partir disso, podemos acessar os campos da tabela usando essas variáveis, lembrando que elas são objetos. Veja alguns exemplos de utilização desses objetos:

queCidadeidcidade.Value;  // lê o valor do campo, inteiro nesse caso
queCidadeidcidade.AsString;  // lê o valor do campo convertido para string

Criação de TFields não é uma novidade. Isso já existia nas versões anteriores. Apenas ficou um pouco mais intuitivo e fácil manipular a criação desses objetos.

Referência aos parâmetros de um comando SQL

Como sabemos, é possível escrever comandos SQL utilizando parâmetros. Um exemplo é mostrado no código abaixo:

procedure TfrmConsCidade.btnPesquisarClick(Sender: TObject);
begin
  with dmDados.queConsCidade do
  begin
    Close;
    SQL.Clear;
    if (rgCampo.ItemIndex = 0) then
    begin
      // pidcidade é um parâmetro
      SQL.Add('select * from cidade where idcidade = :pidcidade');
      // atribuição do valor do parâmetro
      ParamByName('pidcidade').Value := StrToInt(edValor.Text);
      //Params[0].Value := StrToInt(edValor.Text);
    end
    else
    begin
      SQL.Add('select * from cidade where nome like :pnome');
      ParamByName('pnome').Value := edValor.Text + '%';
    end;
    Open;
  end;
end;

Em versões anteriores não havia o método ParamByName(). O acesso a um parâmetro era feito usando Params[]. Isso é mostrado na linha de código 13, que aparece comentada. O uso de ParamByName() torna o código mais legível.
O SQLdb melhorou muito, mas ainda aconselhamos o uso de ZeosLib.

domingo, 1 de maio de 2011

Free Pascal - Variáveis Procedurais

Depois de um longo tempo afastado do blog, estamos retornando. Iremos iniciar uma série de artigos dedicados às estruturas de dados do Free Pascal. Mas antes de iniciar é necessário uma breve introdução a variáveis procedurais.
Variáveis procedurais ou tipos procedurais são um recurso do Free Pascal que permite armazenar métodos, funções e procedimentos em variáveis. Tais variáveis podem ser normalmente tratadas, passando-as como parâmetros e chamando os métodos quando for necessário.
Para exemplificar o uso deste recurso vejamos como declarar um tipo procedural:

type
  TFuncaoSemParametro = function(): String;
  TFuncaoComParametro = function(x: String): String;

O primeiro exemplo declara um tipo que armazena um função que não recebe argumentos. O segundo exemplo declara um tipo que armazena uma função que recebe parâmetros.
Tipos procedurais também podem ser declarados de mais duas maneiras, como pode ser visto abaixo. O primeiro declara um tipo para armazenar um procedimento e o segundo armazena um método de uma classe:

type
   TProcedimento = procedure;
   TMetodo = procedure of Object;

Prosseguindo então com nosso exemplo, em seguida iremos declarar as funções:

function AloMundo: String;
begin
  Result := 'Alo Mundo';
end;

function AloNovamente(S: String): String;
begin
  Result := 'Alo ' + S;
end;

Essas duas funções serão usadas como argumentos nas chamadas aos dois procedimentos seguintes, que recebem como parâmetros os tipos procedurais declarados.

procedure Primeiro(f: TFuncaoSemParametro);
begin
  WriteLn(f());
end;

procedure Segundo(f: TFuncaoComParametro);
begin
  WriteLn(f('Novamente'));
end;                 

Observe que tanto o procedimento Primeiro, quanto o procedimento Segundo executam a função que recebem como parâmetro. As funções chamadas irão retornar Strings que serão escritas no console através de writeln.
Para testar a funcionalidade apenas chame os procedimentos assim:

Primeiro(@AloMundo);
Segundo(@AloNovamente);

O símbolo @ converte a variável em um ponteiro. É desta forma que a função é passada como parâmetro.
É importante observar que o compilador verifica se a função ou o procedimento que está sendo passado como parâmetro corresponde exatamente ao esperado, ou seja, possui os mesmos parâmetros, o mesmo tipo de retorno, etc.
O mecanismo usado pelos eventos de componentes da biblioteca do Lazarus é exatamente este. Veja como pode ser criado um componente dinamicamente e como atribuir um método a um evento de um TButton no post Lazarus - Criando componentes em run-time.
A seguir o código completo da aplicação console:

program procvar;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
type
  TFuncaoSemParametro = function(): String;
  TFuncaoComParametro = function(x: String): String;

function AloMundo: String;
begin
  Result := 'Alo Mundo';
end;

function AloNovamente(S: String): String;
begin
  Result := 'Alo ' + S;
end;

procedure Primeiro(f: TFuncaoSemParametro);
begin
  WriteLn(f());
end;

procedure Segundo(f: TFuncaoComParametro);
begin
  WriteLn(f('Novamente'));
end;

{$R *.res}

begin
  Primeiro(@AloMundo);
  Segundo(@AloNovamente);
  ReadLn;
end.

Atualizado em 03/05/2011.
 
Creative Commons License
This work by Carlos Alberto P. Araújo is licensed under a Creative Commons Atribuição-Uso não-comercial-Compartilhamento pela mesma licença 3.0 Brasil License.