Padrões práticos para integrar o EgStrParser em aplicações de bases de dados.
A utilização mais comum: um campo de edição num formulário de pesquisa, validado ao sair e aplicado a um query.
procedure TfrmOrders.edDateExit(Sender: TObject);
var
R: TParseResult;
begin
R := ParseInput(edDate.Text, itDate);
case R.ResultType of
otEmpty:
// Não há filtro neste campo; remova qualquer fragmento de cláusula WHERE existente.
FDateFilter := '';
otInvalid:
begin
edDate.Color := clYellow;
Exit;
end;
else
edDate.Color := clWindow;
FDateFilter := 'OrderDate ' + R.SQLExpression;
end;
ApplyFilters;
end;R.SQLExpression para otEmpty é preenchida
(contém IS NULL ou = ''), mas o padrão típico
de aplicação é tratar uma entrada vazia como «sem filtro» e remover
completamente o campo da cláusula WHERE.
Os intervalos são detetados automaticamente quando a entrada contém o separador de intervalo. Não é necessário qualquer tratamento especial por parte do chamador.
// O utilizador digita: 100~500
R := ParseInput(edAmount.Text, itDecimal);
// R.ResultType = otRange
// R.SQLExpression = BETWEEN 100.0000 AND 500.0000
// O utilizador digita: 2026-01-01~2026-03-31
R := ParseInput(edDate.Text, itDate);
// R.SQLExpression = BETWEEN DATE '2026-01-01' AND DATE '2026-03-31'As listas também são detetadas automaticamente.
// Tipos de utilizador: 1001;1002;1005
R := ParseInput(edIds.Text, itInteger);
// R.ResultType = otList
// R.SQLExpression = IN (1001, 1002, 1005)
// Tipos de utilizador: smith, jones, o'brien
R := ParseInput(edName.Text, itString, [opTrim]);
// R.SQLExpression = IN ('smith', 'jones', 'O''brien')// Tipos de utilizador: acme
R := ParseInput(edCompany.Text, itString, [opTrim], sopLikeBoth);
// R.SQLExpression = LIKE '%acme%' ESCAPE '\'
Query1.SQL.Text := 'SELECT * FROM Companies WHERE CompanyName ' + R.SQLExpression;Configure TEgStrParser em tempo de design (dialeto,
operador predefinido, opções predefinidas) e chame Parse()
a partir dos manipuladores de eventos.
// No Object Inspector:
// EgParser1.SqlDialect = sqlElevateDB
// EgParser1.DefaultOptions = [opTrim]
procedure TfrmSearch.edNameExit(Sender: TObject);
var
R: TParseResult;
begin
R := EgParser1.Parse(edName.Text, itString, sopLikeRight, Sender as TComponent);
if R.ResultType <> otInvalid then
FNameFilter := 'CustomerName ' + R.SQLExpression;
end;procedure TfrmSearch.FilterExit(Sender: TObject);
var
Ed: TEdit;
R: TParseResult;
Fragment: *string*;
begin
Ed := Sender as TEdit;
if Ed = edOrderDate then
R := EgParser1.Parse(Ed.Text, itDate)
else if Ed = edAmount then
R := EgParser1.Parse(Ed.Text, itDecimal)
else if Ed = edCustomer then
R := EgParser1.Parse(Ed.Text, itString, [opTrim], sopLikeBoth)
else
Exit;
Ed.Color := IfThen(R.ResultType = otInvalid, clYellow, clWindow);
if R.ResultType <> otInvalid then
FFilters.Values[Ed.Name] := R.SQLExpression;
ApplyFilters;
end;
procedura TfrmSearch.ApplyFilters;
var
Key, WhereClause: *string*;
Parts: TStringList;
begin
Parts := TStringList.Create;
try
for Key in FFilters.Keys do
if FFilters.Values[Key] <> '' then
Parts.Add(Key + ' ' + FFilters.Values[Key]);
WhereClause := Parts.CommaText; // ou String.Join(' AND ', ...)
finally
Parts.Free;
end;
// aplicar a *query*...
end;procedure ApplyFieldFilter(const ColName, Input: *string*;
ValueType: TInputType; Query: TQuery);
var
R: TParseResult;
begin
R := ParseInput(Input, ValueType, [opTrim]);
case R.ResultType of
otEmpty:
// Sem filtro: *query* sem uma cláusula WHERE nesta coluna.
Query.SQL.Text := Format('SELECT * FROM T', []);
otInvalid:
raise EValidationError.CreateFmt(
'Valor inválido para %s (erro %d)', [ColName, R.ErrorCode]);
else
// otSingleValue, otList, otRange — todos produzem uma SQLExpression válida.
Query.SQL.Text :=
Format('SELECT * FROM T WHERE %s %s', [ColName, R.SQLExpression]);
end;
Query.Open;
end;Utilize opRequired para rejeitar entradas vazias e
opNotNull para rejeitar posições vazias numa lista.
R := ParseInput(edId.Text, itInteger, [opRequired, opNotNull]);
if R.ErrorCode = ERR_EMPTY_NOT_ALLOWED then
ShowMessage('O ID é obrigatório.')
else if R.ErrorCode = ERR_NULL_NOT_ALLOWED then
ShowMessage('A lista não pode conter posições vazias.')
else if R.ResultType = otInvalid then
ShowMessage('ID inválido.')
else
// utilize R.SQLExpression// O utilizador digita: fatura de pagamento
R := ParseInput(edKeywords.Text, itString, [opTrim], sopContainsAll);
// sqlElevateDB: CONTAINS ALL 'fatura de pagamento'
// outros dialetos: LIKE '%pagamento%fatura%' ESCAPE '\'
Query1.SQL.Text :=
'SELECT * FROM Documents WHERE Body ' + R.SQLExpression;function BuildFilter(const Input: *string*; ValueType: TInputType;
Dialect: TSqlDialect): *string*;
var
R: TParseResult;
begin
R := ParseInput(Input, ValueType, '~', [opTrim], sopEqual, Dialect);
if R.ResultType in [otSingleValue, otList, otRange] then
Result := R.SQLExpression
else
Result := '';
end;O parser aceita formatos de data compactos, ISO e de localização sem qualquer configuração. Os utilizadores podem introduzir qualquer um destes formatos e obter o mesmo resultado SQL:
25/03/2026 → DATE '2026-03-25' (formato local dd/mm/aaaa, pt-PT)
2026-03-25 → DATE '2026-03-25' (ISO)
25032026 → DATE '2026-03-25' (compacto ddmmyyyy)
2503 → DATE '2026-03-25' (compacto ddmm, ano atual)
Não é necessário qualquer pré-processamento do lado do chamador.
Values[] contém a exibição normalizada e adaptada às
configurações regionais strings. Utilize-os para mostrar ao
utilizador o que o parser compreendeu:
R := ParseInput('25032026~31122026', itDate);
// R.Values[0]: '25-03-2026' (configuração regional pt-PT)
// R.Values[1]: '31-12-2026'
// R.ParsedValue: '25-03-2026 ~ 31-12-2026'
lblParsed.Caption := 'Interpretado como: ' + R.ParsedValue;