Query Builder

TsgcHTMLComponent_QueryBuilder: ein visueller Abfrage- und Filter-Builder. Benutzer kombinieren Bedingungen (Feld, Operator, Wert) in UND- und ODER-Gruppen, von Hand oder aus einer Frage in natürlicher Sprache, die der KI-Assistent beantwortet, und der Server macht daraus eine parametrisierte SQL-Bedingung, einen Zeilenabgleich oder einen Filter auf einem Grid, in Delphi, C++ Builder und .NET.

TsgcHTMLComponent_QueryBuilder

Fügen Sie die Felder hinzu, die eine Regel benennen kann, oder verknüpfen Sie ein TsgcHTMLComponent_Grid, um dessen Spalten zu verwenden, und rendern Sie ihn. Jede Schaltfläche sendet ein Server-Ereignis, die Komponente validiert den Baum dieser Anfrage, und OnApply übergibt Ihnen den Baum, um Ihre Daten abzufragen.

Komponentenklasse

TsgcHTMLComponent_QueryBuilder mit TsgcHTMLQueryNode für den Baum der Bedingungen

Rendert

Ein Baum aus Bedingungen und Gruppen als Bootstrap-5-Markup, serverseitig gerendert und ohne Skript

Sprachen

Delphi, C++ Builder, .NET

Felder definieren, Regeln auf Ihre Daten anwenden

Fields listet auf, was eine Regel benennen kann. OnApply erhält den validierten Baum der Anfrage, GetSQLWhere schreibt ihn als SQL-Bedingung mit benannten Parametern, und ToJSON speichert ihn für die Sitzung des Benutzers.

uses
  sgcHTML_AI, sgcHTML_Component_QueryBuilder;

// Einmal erstellt: Es beantwortet seine eigenen Server-Ereignisse
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 ist der Baum dieser Anfrage, Rules bleibt unberührt
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));      // Ihr Sitzungsspeicher
    aResponse := DoOrdersHTML(FDQuery1);   // Zeilen mit hx-swap-oob markiert
  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 ist der Baum dieser Anfrage
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;

Was Ihre Benutzer bekommen

Ein Filterbildschirm für Menschen, die kein SQL schreiben, und eine Bedingung, die Ihr Code auf jeder Datenbank sicher ausführen kann.

UND- und ODER-Gruppen

Jede Bedingung benennt ein Feld, einen Operator und einen oder zwei Werte, und jede Gruppe verbindet ihre Kinder mit UND oder ODER. Gruppen lassen sich bis zu MaxDepth Ebenen tief verschachteln, und ein Baum enthält höchstens MaxRules Regeln. Bedingung hinzufügen und Gruppe hinzufügen beginnen mit dem ersten wirksamen Feld.

Operatoren nach Datentyp

Der DataType eines Felds bestimmt, welche Operatoren der Benutzer wählen kann: ist gleich, ist ungleich, enthält, beginnt mit, endet mit, ist größer als, ist kleiner als, liegt zwischen, ist einer von, ist leer und ist nicht leer. Ein Feld mit Options, einer geschlossenen Werteliste, erlaubt eine kürzere Liste.

In natürlicher Sprache fragen

Mit einem AIAssistant und AIPrompt True verwandelt ein Fragen-Feld eine Frage in UND-Regeln über die wirksamen Felder. Die Regeln landen im Builder, wo der Benutzer sie vor dem Anwenden noch ändern kann, und die Erklärung der Antwort erscheint unter dem Feld.

Funktioniert ohne API-Schlüssel

Ein Assistent ohne konfigurierten Anbieter antwortet mit seinem regelbasierten Parser, sodass das Fragen-Feld offline funktioniert. Wenn ein Aufruf des Anbieters fehlschlägt, lässt UseRuleBasedFallback (standardmäßig True) denselben Parser antworten.

Mit dem Grid verknüpft

Verknüpfen Sie ein TsgcHTMLComponent_Grid, und der Builder übernimmt seine Felder aus den Grid-Spalten, wenn Fields leer ist. ApplyToGrid filtert die Zeilen des Grids über dessen RowFilter, und LoadFromGridOps füllt einen Baum mit einer Regel pro Filter einer Grid-Operationsmenge.

Auch für einfache Formulare

Jedes Steuerelement heißt <ElementName>.<path>.<key>, wobei der Pfad der Indexpfad des Knotens ist und der Schlüssel den Kombinator, das Feld, den Operator oder den Wert benennt. LoadFromRequest liest diese Namen wieder ein, sodass der Builder auch in einem einfachen, ohne htmx gesendeten Formular funktioniert.

Wichtige Eigenschaften, Methoden & Ereignisse

Die Member, zu denen Sie am häufigsten greifen.

Fields

Fields enthält die Felder, die eine Regel benennen kann, jeweils mit Caption, DataType, SQLName und optionalen Options, ein Wert oder value=caption pro Zeile. Ohne Einträge sind die Spalten von Grid die wirksamen Felder. FindField, GetFieldCount und IsOperatorAllowed beantworten Fragen dazu.

OnApply

OnApply(Sender, aRules, aResponse) wird nach Apply, Clear und einer beantworteten Frage mit dem validierten Baum der Anfrage ausgelöst. Was Sie in aResponse zurückgeben, wird an die Antwort angehängt, zum Beispiel Ihre mit hx-swap-oob markierten Zeilen. Ohne OnApply kopiert ApplyToGrid den Baum nach Rules und filtert das verknüpfte Grid.

GetSQLWhere

Gibt die Bedingung ohne das Schlüsselwort WHERE zurück, bei einem leeren Baum eine leere Zeichenfolge. Werte werden nur als benannte Parameter :qb1, :qb2 und so weiter geschrieben, jeweils als qb1=<value> zu aParams hinzugefügt, sodass der Text des Benutzers die Anweisung nicht ändern kann. Die Spalte ist der SQLName des Felds oder sein Name.

Validiert, nie vertraut

Alles, was einen Baum von außen füllt, JSON, eine KI-Antwort oder ein gesendetes Formular, durchläuft dieselbe Validierung. Regeln auf Feldern, die nicht wirksam sind, Operatoren, die der Typ nicht erlaubt, Regeln über MaxRules und Gruppen, die tiefer als MaxDepth liegen, werden verworfen, Werte werden auf 200 Zeichen gekürzt und leere Untergruppen entfernt. SQLName geht unverändert ins SQL, setzen Sie ihn daher im Code und nie aus einer Anfrage.

Das JSON-Format

ToJSON schreibt eine Gruppe als {"c":"and","r":[...]} und eine Regel als {"f":"field","o":"operator","v":"value"}, bei zwischen zusätzlich "v2". ParseJSON und LoadFromJSON lesen es wieder ein und validieren es.

Matches

Matches wertet den Baum auf einer Zeile aus, die als Name=Value-Paare angegeben ist, für Zeilen im Speicher. Jeder Helfer nimmt einen optionalen Baum, und nil bedeutet Rules, sodass ein OnApply-Handler auf dem Baum der Anfrage arbeitet, ohne die gemeinsame Komponente anzufassen.

Mehrere Benutzer

Eine Komponente bedient jede Sitzung, weil das Server-Ereignis auf dem Baum der Anfrage arbeitet. Weisen Sie auf einer von mehreren Benutzern geteilten Seite OnApply zu, speichern Sie ToJSON(aRules) in der Sitzung und rendern Sie den Builder jedes Benutzers mit ParseJSON und GetBuilderHTML.

Das Server-Ereignis

Jede Schaltfläche sowie die Feld- und Operatorauswahl bei einer Änderung senden das Server-Ereignis qb an den Komponenten-Ereignis-Endpunkt der HTMX-Engine oder an ActionURL. Die Antwort ist der mit hx-swap-oob="true" markierte Builder, den htmx anhand seiner ID ersetzt: QueryBuilderID oder qb_ plus ElementName.

Die Demo

Demos\60.HTML\01.RunTime\25.QueryBuilder ist eine Bestellseite auf Port 8127 mit dem Builder über dem Grid und einer SQL-Karte, die die parametrisierte WHERE-Klausel zeigt, die dieselben Regeln auf einer Datenbank ausführen würden. Der KI-Assistent hat keinen API-Schlüssel, sodass das Fragen-Feld offline antwortet, und jeder Besucher behält seine eigenen Regeln in der Sitzung. Die Designtime-, Lazarus- und .NET-Versionen spiegeln sie.

Weiter entdecken

Online ausprobierenSehen Sie es in der Demo Abfrage-Builder, live auf dem eSeGeCe-Demoserver.
Online-HilfeVollständige API-Referenz und Verwendungshandbuch für diese Komponente.
Grid-KomponenteDas Grid, das der Builder filtert und aus dem er seine Spalten übernimmt.
KI-AssistentVerwandelt eine Frage in natürlicher Sprache in die Regeln des Fragen-Felds.
Alle sgcHTML-KomponentenDurchsuchen Sie die vollständige Funktionsmatrix von über 80 Komponenten.
Kostenlose Testversion herunterladenDie 30-Tage-Testversion enthält die 60.HTML-Demoprojekte.
PreiseSingle-, Team- und Site-Lizenzen mit vollständigem Quellcode.
Bestes Preis-Leistungs-Verhältnis: All-AccessAlle eSeGeCe-Produkte, inklusive Premium-Support, ab €1,059 pro Jahr.
All-Access-Preise ansehen

Bereit loszulegen?

Laden Sie die kostenlose Testversion herunter und beginnen Sie, Web-UIs in Delphi, C++ Builder und .NET zu erstellen.