Query Builder

TsgcHTMLComponent_QueryBuilder: un costruttore visuale di query e filtri. Gli utenti combinano condizioni (campo, operatore, valore) in gruppi AND e OR, a mano o a partire da una domanda in linguaggio naturale a cui risponde l'AI Assistant, e il server trasforma il risultato in una condizione SQL parametrizzata, una corrispondenza di righe o un filtro su un Grid, in Delphi, C++ Builder e .NET.

TsgcHTMLComponent_QueryBuilder

Aggiungi i campi che una regola può nominare, oppure collega un TsgcHTMLComponent_Grid per usarne le colonne, e visualizzalo. Ogni pulsante invia un evento server, il componente valida l'albero di quella richiesta e OnApply ti consegna l'albero per interrogare i tuoi dati.

Classe del componente

TsgcHTMLComponent_QueryBuilder, con TsgcHTMLQueryNode per l'albero delle condizioni

Rendering

Un albero di condizioni e gruppi come markup Bootstrap 5, renderizzato sul server e senza script

Famiglia

Moduli e Input

Linguaggi

Delphi, C++ Builder, .NET

Definisci i campi, esegui le regole sui tuoi dati

Fields elenca ciò che una regola può nominare. OnApply riceve l'albero validato della richiesta, GetSQLWhere lo scrive come condizione SQL con parametri con nome e ToJSON lo conserva per la sessione dell'utente.

uses
  sgcHTML_AI, sgcHTML_Component_QueryBuilder;

// Creato una sola volta: risponde ai propri eventi server
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 è l'albero di questa richiesta, Rules non viene toccato
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));      // il tuo archivio di sessione
    aResponse := DoOrdersHTML(FDQuery1);   // righe marcate con 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 è l'albero di questa richiesta
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;

Cosa ottengono i tuoi utenti

Una schermata di filtri per chi non scrive SQL e una condizione che il tuo codice può eseguire in sicurezza su qualsiasi database.

Gruppi AND e OR

Ogni condizione nomina un campo, un operatore e uno o due valori, e ogni gruppo unisce i suoi figli con AND oppure OR. I gruppi si annidano fino a MaxDepth livelli e un albero contiene al massimo MaxRules regole. Aggiungi condizione e Aggiungi gruppo partono dal primo campo in vigore.

Operatori in base al tipo di dato

Il DataType di un campo decide quali operatori l'utente può scegliere: uguale, diverso, contiene, inizia con, finisce con, maggiore, minore, tra, in elenco, è vuoto e non è vuoto. Un campo con Options, un elenco chiuso di valori, ammette un elenco più breve.

Chiedi in linguaggio naturale

Con un AIAssistant e AIPrompt a True, una casella Chiedi trasforma una domanda in regole AND sui campi in vigore. Le regole arrivano nel builder, dove l'utente può ancora modificarle prima di applicarle, e la spiegazione della risposta compare sotto la casella.

Funziona senza chiave API

Un assistente senza provider configurato risponde con il proprio parser basato su regole, quindi la casella Chiedi funziona offline. Quando una chiamata al provider fallisce, UseRuleBasedFallback (True di default) lascia rispondere lo stesso parser.

Collegato al Grid

Collega un TsgcHTMLComponent_Grid e il builder prende i suoi campi dalle colonne del grid quando Fields è vuoto. ApplyToGrid filtra le righe del grid tramite il suo RowFilter, e LoadFromGridOps riempie un albero con una regola per ogni filtro di un insieme di operazioni del grid.

Anche con moduli semplici

Ogni controllo si chiama <ElementName>.<path>.<key>, dove path è il percorso degli indici del nodo e key nomina il combinatore, il campo, l'operatore o il valore. LoadFromRequest rilegge quei nomi, quindi il builder funziona anche dentro un modulo semplice inviato senza htmx.

Proprietà, metodi ed eventi principali

I membri che usi più spesso.

Campi

Fields contiene i campi che una regola può nominare, ciascuno con il proprio Caption, DataType, SQLName e Options facoltativo, un valore o value=caption per riga. Senza elementi, le colonne di Grid sono i campi in vigore. FindField, GetFieldCount e IsOperatorAllowed rispondono a domande su di essi.

OnApply

OnApply(Sender, aRules, aResponse) scatta dopo Applica, Cancella e una domanda con risposta, con l'albero validato della richiesta. Ciò che restituisci in aResponse viene aggiunto alla risposta, per esempio le tue righe marcate con hx-swap-oob. Senza OnApply, ApplyToGrid copia l'albero in Rules e filtra il Grid collegato.

GetSQLWhere

Restituisce la condizione senza la parola chiave WHERE, o una stringa vuota per un albero vuoto. I valori sono scritti solo come i parametri con nome :qb1, :qb2 e così via, ciascuno aggiunto a aParams come qb1=<value>, quindi il testo dell'utente non può cambiare l'istruzione. La colonna è il SQLName del campo, oppure il suo Name.

Validato, mai considerato attendibile

Tutto ciò che riempie un albero dall'esterno, JSON, una risposta dell'IA o un modulo inviato, passa per la stessa validazione. Vengono scartate le regole su campi non in vigore, gli operatori che il tipo non ammette, le regole oltre MaxRules e i gruppi più profondi di MaxDepth, i valori sono tagliati a 200 caratteri e i sottogruppi vuoti sono rimossi. SQLName entra nell'SQL così com'è, quindi impostalo nel codice e mai da una richiesta.

Il formato JSON

ToJSON scrive un gruppo come {"c":"and","r":[...]} e una regola come {"f":"field","o":"operator","v":"value"}, più "v2" per tra. ParseJSON e LoadFromJSON lo rileggono e lo validano.

Matches

Matches valuta l'albero su una riga data come coppie Name=Value, per righe tenute in memoria. Ogni helper accetta un albero facoltativo, e nil significa Rules, quindi un gestore di OnApply lavora sull'albero della richiesta senza toccare il componente condiviso.

Più utenti

Un solo componente serve ogni sessione, perché l'evento server lavora sull'albero della richiesta. In una pagina condivisa da più utenti, assegna OnApply, conserva ToJSON(aRules) nella sessione e renderizza il builder di ogni utente con ParseJSON e GetBuilderHTML.

L'evento server

Ogni pulsante, e i select di campo e operatore quando cambiano, inviano l'evento server qb all'endpoint degli eventi dei componenti del motore HTMX, oppure a ActionURL. La risposta è il builder marcato con hx-swap-oob="true", che htmx sostituisce tramite il suo id: QueryBuilderID, oppure qb_ più ElementName.

La demo

Demos\60.HTML\01.RunTime\25.QueryBuilder è una pagina di ordini sulla porta 8127 con il builder sopra il grid e una scheda SQL che mostra la clausola WHERE parametrizzata che le stesse regole eseguirebbero su un database. Il suo AI Assistant non ha chiave API, quindi la casella Chiedi risponde offline, e ogni visitatore conserva le proprie regole nella sessione. Le versioni design time, Lazarus e .NET lo replicano.

Continua a esplorare

Provalo onlineGuardalo nella demo Generatore di query, in esecuzione dal vivo sul server demo di eSeGeCe.
Guida in lineaRiferimento API completo e guida all'uso di questo componente.
Componente GridIl grid che il builder filtra e da cui prende le colonne.
AI AssistantTrasforma una domanda in linguaggio naturale nelle regole della casella Chiedi.
Tutti i componenti sgcHTMLEsplora la matrice completa delle funzionalità di oltre 80 componenti.
Scarica la Prova GratuitaLa prova di 30 giorni include i progetti demo 60.HTML.
PrezziLicenze Single, Team e Site con codice sorgente completo.
La scelta più conveniente: All-AccessTutti i prodotti eSeGeCe, con Supporto Premium incluso, a partire da €1,059/anno.
Vedi i prezzi All-Access

Pronto a Iniziare?

Scarica la versione di prova gratuita e inizia a creare interfacce web in Delphi, C++ Builder e .NET.