sexta-feira, 6 de outubro de 2017

DROP Wiki #3 - Instruções SQL via texto

Por mais que um ORM tenha o objetivo de não escrever explicitamente instruções SQL, usuários novos de ORMs tendem a não aceitar uma ferramenta que não permita usar uma instrução SQL escrita manualmente. Em outras palavras, a aceitação de um framework com suporte a ORM passa por também suportar SQLs via texto, é quase que uma válvula de escape para desenvolvedores que não dominam ou até mesmo não confiam 100% na técnica.

No post anterior, foi apresentada a lista de classes nativas do DROP para estabelecimento de conexões com os SGBDs suportados. Como estratégia de evolução na apresentação e uso dos recursos do DROP, este post demonstrará como conversar com o SGBD, via instruções SQL escritas manualmente.

Os exemplos a seguir serão implementados sobre o Interbase, mas como já mencionado no post anterior, os recursos apresentados aqui estão disponíveis para todos os SGBDs suportados pelo DROP. Para os exemplos abaixo, assuma que já existe um objeto de conexão instanciado, e apontando para a tradicional base de exemplos Employee.

Inicialmente, o DROP não possui componentes ou objetos a parte para executar os comandos, como os tradicionais TSQLQuery, TFDQuery, entre outros. Todos os acessos e manipulações de dados são executados diretamente a partir do objeto de conexão com o SGBD.

Para começar, vamos buscar dados através de um select simples. As instruções SQL que retornam cursores são executadas através do método OpenQuery. Uma das sobrecargas do OpenQuery permite passar diretamente o texto de um select (demais sobrecargas serão demonstradas em outro post). Todas as sobrecargas do método OpenQuery retornam uma implementação da interface IAqDBReader.

A interface IAqDBReader foi especificada visando ser uma camada de acesso muito fina entre o seu código e os dados do cursor aberto pela instrução SQL. Portanto, o retorno não faz cache, e é unidirecional. Também é muito importante dizer que a leitura do primeiro registro passa obrigatoriamente pela primeira chamada do método Next no reader (ao estilo DBX Framework e readers de outras linguagens). E por fim, existem duas maneiras de ler colunas do cursor, as tradicionais referências por índice ou nome das mesmas.

O exemplo abaixo demonstra a leitura de todos os países da base, e então a alimentação de um componente memo com cada um dos nomes retornados.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
procedure TfrmExemplos.btnSelectClick(Sender: TObject);
var
  lReader: IAqDBReader;
begin
  mmoResultados.Lines.Clear;

  lReader := FConexao.OpenQuery('select country from country');

  while lReader.Next do
  begin
//    mmoResultados.Lines.Add(lReader.Values[0].AsString);
    mmoResultados.Lines.Add(lReader.Values['country'].AsString);
  end;
end;

Note que no laço de alimentação do memo constam duas linhas. A primeira linha, que está comentada e, portanto, sem efeito, o índice da coluna seria usado para referenciá-la, e na segunda linha, acessamos o valor da coluna através do seu nome.

Aos que não estão habituados com este conceito de reader, é necessário salientar que o método Next já é responsável por informar se o cursor chegou ao seu fim ou não, fazendo com que o teste de quebra do laço realize a troca do registro apontado pelo cursor.

O próximo exemplo visa demonstrar uma variação do exemplo acima, desta vez criando um parâmetro para execução da consulta.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
procedure TfrmExemplos.btnSelectComParametrosClick(Sender: TObject);
var
  lReader: IAqDBReader;
begin
  mmoResultados.Lines.Clear;

  lReader := FConexao.OpenQuery(
    'select country from country where currency = :currency',
    procedure(pParametros: IAqDBParameters)
    begin
      pParametros['currency'].AsString := 'Euro';
    end);

  while lReader.Next do
  begin
    mmoResultados.Lines.Add(lReader.Values['country'].AsString);
  end;
end;

É possível observar que a criação de parâmetros segue o tradicional padrão de quase todas as engines de acesso a dados do Delphi, com a prefixação do parâmetro com o caractere ':'. A principal diferença do DROP às demais metodologias está na passagem dos valores dos parâmetros, que acontece com um método anônimo (callback) que dá acesso aos parâmetros antes da execução da instrução contra o SGBD.

Como nota importante do exemplo acima, é importante dizer que, mesmo quando usando o DBX Framework como engine da conexão do DROP, o método de parâmetros nomeados também está disponível. Para quem não lembra, o DBX Framework não suporta parâmetros nomeados, mas o DROP realiza um parse sobre a instrução SQL, mapeia os parâmetros, e então faz o meio de campo entre os parâmetros do DBX e os parâmetros disponibilizados ao usuário, podendo estes serem acessados também via nome.

Por fim, vamos a um exemplo de instrução de DML. Estes comandos são executados a partir do método ExecuteCommand, que entre outras sobrecargas, também possui a capacidade de receber uma instrução de DML via texto, e passagens dos parâmetros via callback. Observe o exemplo abaixo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
procedure TfrmExemplos.btnUpdateClick(Sender: TObject);
var
  lRegistrosAfetados: Int64;
begin
  lRegistrosAfetados := FConexao.ExecuteCommand(
    'update country set currency = :currency where country = :country',
    procedure(pParametros: IAqDBParameters)
    begin
      pParametros['currency'].AsString := 'US Dollar';
      pParametros['country'].AsString := 'USA';
    end);

  ShowMessage(lRegistrosAfetados.ToString);
end;

Dúvidas? Por favor, não hesite em me contatar através do mail tatu@taturs.com, ou ainda por drop@aquasoft.com.br.

Abraço e até o próximo post!

Nenhum comentário:

Postar um comentário

DROP Wiki #3 - Instruções SQL via texto

Por mais que um ORM tenha o objetivo de não escrever explicitamente instruções SQL, usuários novos de ORMs tendem a não aceitar uma ferramen...