quinta-feira, 16 de fevereiro de 2012

Delphi SqlBuilder

Olá, há algum tempo eu havia desenvolvido uma rotina para modificar a cláusula Where de sql statements(pelo menos dos mais simples). Agora surgiu a oportunidade de compartilhar a solução, então aqui está.

Logo abaixo podemos ver a definição da classe.

TSqlBuilder = class
  private
  public
    class function AddWhere(ASql, AWhere: String; AMainTable: String = ''): String;
    class function ChangeOrdeBy(ASql, AOrderFields: String): String;
  class function RemoveOrderBy(ASql: String): String;
  end;

Como podem ver a definição da classe é bastante simples e possui apenas funções de classe, nada de parser's de sql complicados. O argumento "AWhere' já deve estar formatado ao chamar a função, dando mais liberdade ao desenvolvedor para manipular a claúsula Where da maneira mais conveniente, por exemplo:

var
  qry: TAlgumTipoDeQuery;
begin
  (...)
 qry.Sql.Text := 'Select * from TabelaA Where X = 1';
  
 //Native Types
 qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, ' Y = ''a''');
 qry.Open;
 
 //Bind Parameters
 qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, ' Y = :Y');
 qry.ParamByName('Y').AsString := 'a'
 qry.Open;
end; 

O argumento adicional "AMainTable" que ainda não foi utilizado, é importante quando temos um sql que possui um subselect antes da claúsula from, por exemplo, veja o sql abaixo:
Select a, 
        (select b.b from Tabela2 b where b.x = 3) as b
    from Tabela1 a
   where a.x = 2

Por padrão a claúsula "Where" será adicionada ao primeiro "from' encontrado, no caso, adicionando imediatamente após "Tabela2". Para evitar que isso aconteça, devemos informar qual é a tabela principal do sql, passando como argumento para o método AddWhere o valor "Tabela1".

qry.Sql.Text := 'Select a, ' +
                  '       (select b.b from Tabela2 b where b.x = 3) as b ' +
                   '  from Tabela1 a ' +
                   ' where a.x = 2';
   qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, ' Y = :Y', 'Tabela1');
 

Também temos o método ChangeOrdeBy, que adiciona ou modifica a cláusula "Order by". O modo de usar o mesmo é como segue:

var
  qry: TAlgumTipoDeQuery;
begin
  (...)
 qry.Sql.Text := 'Select * from TabelaA';
 qry.Sql.Text := TSqlBuilder.ChangeOrdeBy(qry.Sql.Text, 'a');
 //Retorna "Select * from TabelaA order by a"
 
 qry.Sql.Text := 'Select * from TabelaA oder by a';
 qry.Sql.Text := TSqlBuilder.ChangeOrdeBy(qry.Sql.Text, 'b asc, c desc');
 //Retorna "Select * from TabelaA order by b asc, c desc"

E por último, o método RemoveOrderBy, que remove qualquer cláusula "Order by" que exista.

O código completo contendo os testes unitários está disponível aqui.

Qualquer sugestão, bug ou melhoria, façam um fork, modifiquem e façam um pull request que eu atualizo aqui, ou abra uma Issue no site do projeto, mais não deixe de me avisar. ;)

Abraços.

Nenhum comentário:

Postar um comentário