Query Builder

TsgcHTMLComponent_QueryBuilder: um construtor visual de consultas e filtros. Os usuários combinam condições (campo, operador, valor) em grupos AND e OR, manualmente ou a partir de uma pergunta em linguagem natural respondida pelo AI Assistant, e o servidor transforma o resultado em uma condição SQL parametrizada, uma correspondência de linha ou um filtro em uma Grid, em Delphi, C++ Builder e .NET.

TsgcHTMLComponent_QueryBuilder

Adicione os campos que uma regra pode nomear, ou vincule uma TsgcHTMLComponent_Grid para usar as suas colunas, e renderize. Cada botão envia um evento de servidor, o componente valida a árvore dessa requisição, e OnApply entrega a árvore para você consultar os seus dados.

Classe do componente

TsgcHTMLComponent_QueryBuilder, com TsgcHTMLQueryNode para a árvore de condições

Renderiza

Uma árvore de condições e grupos como marcação Bootstrap 5, renderizada no servidor e sem script

Linguagens

Delphi, C++ Builder, .NET

Defina os campos, execute as regras sobre os seus dados

Fields lista o que uma regra pode nomear. OnApply recebe a árvore validada da requisição, GetSQLWhere a escreve como uma condição SQL com parâmetros nomeados, e ToJSON a guarda para a sessão do usuário.

uses
  sgcHTML_AI, sgcHTML_Component_QueryBuilder;

// Created once: it answers its own server events
oQB := TsgcHTMLComponent_QueryBuilder.Create(Self);
oQB.ElementName := 'orders';
oField := oQB.Fields.Add;
oField.Name := 'customer';
oField.Caption := 'Customer';
oField := oQB.Fields.Add;
oField.Name := 'amount';
oField.Caption := 'Amount';
oField.DataType := aidtInteger;
oField.SQLName := 'o.amount';
oField := oQB.Fields.Add;
oField.Name := 'status';
oField.Caption := 'Status';
oField.Options.Add('open=Open');
oField.Options.Add('paid=Paid');
oQB.HTMXEngine := HTMXEngine1;
oQB.AIAssistant := sgcHTMLAIAssistant1;
oQB.OnApply := QueryBuilderApply;
Result := oQB.HTML;

// aRules is the tree of this request, Rules is not touched
procedure TForm1.QueryBuilderApply(Sender: TObject;
  const aRules: TsgcHTMLQueryNode; var aResponse: string);
var
  oQB: TsgcHTMLComponent_QueryBuilder;
  oParams: TStringList;
  vWhere: string;
  i: Integer;
begin
  oQB := TsgcHTMLComponent_QueryBuilder(Sender);
  oParams := TStringList.Create;
  try
    vWhere := oQB.GetSQLWhere(oParams, aRules);
    FDQuery1.Close;
    FDQuery1.SQL.Text := 'select * from orders';
    if vWhere <> '' then
      FDQuery1.SQL.Add('where ' + vWhere);
    for i := 0 to oParams.Count - 1 do
      FDQuery1.Params.ParamByName(oParams.Names[i]).AsString :=
        oParams.ValueFromIndex[i];
    FDQuery1.Open;
    DoSaveFilter(oQB.ToJSON(aRules));      // your session store
    aResponse := DoOrdersHTML(FDQuery1);   // rows marked hx-swap-oob
  finally
    oParams.Free;
  end;
end;
// includes: sgcHTML_AI.hpp, sgcHTML_Component_QueryBuilder.hpp
oQB = new TsgcHTMLComponent_QueryBuilder(this);
oQB->ElementName = "orders";
TsgcHTMLQueryField *oField = oQB->Fields->Add();
oField->Name = "customer";
oField->Caption = "Customer";
oField = oQB->Fields->Add();
oField->Name = "amount";
oField->Caption = "Amount";
oField->DataType = aidtInteger;
oField->SQLName = "o.amount";
oQB->HTMXEngine = HTMXEngine1;
oQB->OnApply = QueryBuilderApply;
html = oQB->HTML;

void __fastcall TForm1::QueryBuilderApply(TObject *Sender,
  TsgcHTMLQueryNode* const aRules, UnicodeString &aResponse)
{
  TsgcHTMLComponent_QueryBuilder *oQB = (TsgcHTMLComponent_QueryBuilder *)Sender;
  TStringList *oParams = new TStringList();
  try
  {
    UnicodeString vWhere = oQB->GetSQLWhere(oParams, aRules);
    FDQuery1->Close();
    FDQuery1->SQL->Text = "select * from orders";
    if (vWhere != "")
      FDQuery1->SQL->Add("where " + vWhere);
    for (int i = 0; i < oParams->Count; i++)
      FDQuery1->Params->ParamByName(oParams->Names[i])->AsString =
        oParams->ValueFromIndex[i];
    FDQuery1->Open();
    DoSaveFilter(oQB->ToJSON(aRules));
    aResponse = DoOrdersHTML(FDQuery1);
  }
  __finally
  {
    delete oParams;
  }
}
using esegece.sgcWebSockets;

var qb = new TsgcHTMLComponent_QueryBuilder();
qb.ElementName = "orders";
var field = qb.Fields.Add();
field.Name = "customer";
field.Caption = "Customer";
field = qb.Fields.Add();
field.Name = "amount";
field.Caption = "Amount";
field.DataType = TsgcHTMLAIDataType.aidtInteger;
field.SQLName = "o.amount";
qb.HTMXEngine = htmxEngine;
qb.AIAssistant = aiAssistant;

// aRules is the tree of this request
qb.OnApply += (object sender, TsgcHTMLQueryNode aRules, ref string aResponse) =>
{
    var parameters = new List<string>();
    string where = qb.GetSQLWhere(parameters, aRules);
    using var cmd = connection.CreateCommand();
    cmd.CommandText = "select * from orders" + (where != "" ? " where " + where : "");
    foreach (var p in parameters)
    {
        var kv = p.Split(new[] { '=' }, 2);
        cmd.Parameters.AddWithValue(":" + kv[0], kv[1]);
    }
    DoSaveFilter(qb.ToJSON(aRules));
    aResponse = DoOrdersHTML(cmd.ExecuteReader());
};

string html = qb.HTML;

O que seus usuários recebem

Uma tela de filtros para pessoas que não escrevem SQL, e uma condição que o seu código pode executar com segurança em qualquer banco de dados.

Grupos AND e OR

Cada condição nomeia um campo, um operador e um ou dois valores, e cada grupo une os seus filhos com AND ou OR. Os grupos se aninham até MaxDepth níveis e uma árvore tem no máximo MaxRules regras. Adicionar condição e Adicionar grupo começam no primeiro campo em vigor.

Operadores por tipo de dado

O DataType de um campo decide quais operadores o usuário pode escolher: igual, diferente, contém, começa com, termina com, maior, menor, entre, na lista, está vazio e não está vazio. Um campo com Options, uma lista fechada de valores, permite uma lista menor.

Pergunte em linguagem natural

Com um AIAssistant e AIPrompt True, uma caixa Ask transforma uma pergunta em regras AND sobre os campos em vigor. As regras chegam ao construtor, onde o usuário ainda pode alterá-las antes de aplicar, e a explicação da resposta aparece sob a caixa.

Funciona sem chave de API

Um assistente sem provedor configurado responde com o seu analisador baseado em regras, de modo que a caixa Ask funciona offline. Quando uma chamada ao provedor falha, UseRuleBasedFallback (True por padrão) deixa o mesmo analisador responder.

Vinculado à Grid

Vincule uma TsgcHTMLComponent_Grid e o construtor toma os seus campos das colunas da grade quando Fields está vazio. ApplyToGrid filtra as linhas da grade pelo seu RowFilter, e LoadFromGridOps preenche uma árvore com uma regra por filtro de um conjunto de operações da grade.

Também para formulários simples

Cada controle é chamado <ElementName>.<path>.<key>, onde path é o caminho de índices do nó e key nomeia o combinador, o campo, o operador ou o valor. LoadFromRequest lê esses nomes de volta, de modo que o construtor também funciona dentro de um formulário simples enviado sem htmx.

Principais propriedades, métodos & eventos

Os membros que você mais usa.

Campos

Fields contém os campos que uma regra pode nomear, cada um com seu Caption, DataType, SQLName e Options opcionais, um valor ou value=caption por linha. Sem itens, as colunas de Grid são os campos em vigor. FindField, GetFieldCount e IsOperatorAllowed respondem a perguntas sobre eles.

OnApply

OnApply(Sender, aRules, aResponse) dispara após Aplicar, Limpar e um Ask respondido, com a árvore validada da requisição. O que você devolve em aResponse é anexado à resposta, por exemplo as suas linhas marcadas com hx-swap-oob. Sem OnApply, ApplyToGrid copia a árvore para Rules e filtra a Grid vinculada.

GetSQLWhere

Devolve a condição sem a palavra-chave WHERE, ou uma string vazia para uma árvore vazia. Os valores são escritos apenas como os parâmetros nomeados :qb1, :qb2 e assim por diante, cada um adicionado a aParams como qb1=<value>, de modo que o texto do usuário não pode alterar a instrução. A coluna é o SQLName do campo, ou o seu Name.

Validado, nunca presumido confiável

Tudo que preenche uma árvore a partir de fora, JSON, uma resposta de IA ou um formulário enviado, passa pela mesma validação. Regras sobre campos que não estão em vigor, operadores que o tipo não permite, regras além de MaxRules e grupos mais profundos que MaxDepth são descartados, os valores são cortados em 200 caracteres e os subgrupos vazios são removidos. SQLName entra no SQL como está, então defina-o no código e nunca a partir de uma requisição.

O formato JSON

ToJSON escreve um grupo como {"c":"and","r":[...]} e uma regra como {"f":"field","o":"operator","v":"value"}, mais "v2" para between. ParseJSON e LoadFromJSON o leem de volta e o validam.

Correspondências

Matches avalia a árvore sobre uma linha dada como pares Name=Value, para linhas mantidas em memória. Todo auxiliar aceita uma árvore opcional, e nil significa Rules, de modo que um manipulador de OnApply trabalha sobre a árvore da requisição sem tocar no componente compartilhado.

Vários usuários

Um componente atende todas as sessões, porque o evento de servidor trabalha sobre a árvore da requisição. Em uma página compartilhada por vários usuários, atribua OnApply, guarde ToJSON(aRules) na sessão, e renderize o construtor de cada usuário com ParseJSON e GetBuilderHTML.

O evento de servidor

Cada botão, e os selects de campo e de operador quando mudam, enviam o evento de servidor qb ao endpoint de eventos de componentes do motor HTMX, ou a ActionURL. A resposta é o construtor marcado com hx-swap-oob="true", que o htmx substitui pelo seu id: QueryBuilderID, ou qb_ mais ElementName.

A demo

Demos\60.HTML\01.RunTime\25.QueryBuilder é uma página de pedidos na porta 8127 com o construtor acima da grade e um cartão de SQL que mostra a cláusula WHERE parametrizada que as mesmas regras executariam em um banco de dados. Seu AI Assistant não tem chave de API, então a caixa Ask responde offline, e cada visitante mantém as suas próprias regras na sessão. As versões em design time, Lazarus e .NET a espelham.

Continue explorando

Experimente onlineVeja na demo Construtor de consultas, rodando ao vivo no servidor de demos da eSeGeCe.
Ajuda onlineReferência completa da API e guia de uso para este componente.
Componente GridA grade que o construtor filtra e da qual toma as colunas.
Componente AI AssistantTransforma uma pergunta em linguagem natural nas regras da caixa Ask.
Todos os Componentes sgcHTMLExplore a matriz completa de recursos com mais de 80 componentes.
Baixar Versão de Avaliação GratuitaA avaliação de 30 dias inclui os projetos de demonstração 60.HTML.
PreçosLicenças Single, Team e Site com código-fonte completo.
Melhor custo-benefício: All-AccessTodos os produtos da eSeGeCe, com Suporte Premium incluído, a partir de €1,059/ano.
Ver preços do All-Access

Pronto para Começar?

Baixe a versão de avaliação gratuita e comece a construir UIs web em Delphi, C++ Builder e .NET.