Writing Expressions (FireDAC)

From RAD Studio
Jump to: navigation, search

Go Up to Working with DataSets (FireDAC)


FireDAC offers powerful client expressions engine, used for filtering, indexing, and calculated fields.

General

FireDAC supports expression syntax compatible with:

  • BDE data access components
  • TClientDataset
  • Oracle 8 (not for 100%)
  • ODBC escape functions

To add Oracle-like, ODBC-like, and regular expression functions, you need to include the FireDAC.Stan.ExprFuncs unit into any application uses clause. Otherwise you can get an error, such as "Column with name [NVL] is not found". Here is a list of registered functions:

The expression engine supports FireDAC escape sequences. Also, the dataset fields may be referenced in an expression, as the identifiers. For example:

FDQuery1.Filter := 'upper(name) like ''bill%''';
FDQuery1.Filtered := True;

Or:

FDQuery1.Filter := '(upper(rtrim(name)) like ''bill%'') or (upper(rtrim(name)) like ''john%'')';
FDQuery1.Filtered := True;

If you need to create your own function and register it with FireDAC, see the FireDAC.Stan.ExprFuncs.pas unit for details.

Using Expression for Custom Purposes

An application can use the FireDAC expression evaluator to perform text formula calculations. There are two basic options:

var
  oEval: IFDStanExpressionEvaluator;
...
oEval := FDMemTable1.CreateExpresison('(sal + comm) * tax / 100');
Label1.Caption := oEval.Evaluate;
...
FDMemTable1.Next;
oEval.DataSource.Position := FDMemTable1.GetRow;
Label1.Caption := oEval.Evaluate;
...
oEval := nil;
FDMemTable1.Close;
  • Use the API to extend the evaluator by custom data source. For example:
uses
  FireDAC.Stan.Intf, FireDAC.Stan.Factory, FireDAC.Stan.Expr, FireDAC.Stan.ExprFuncs;

type
  TMyVariable = class (TInterfacedObject, IFDStanExpressionDataSource)
  private
    FName: String;
    FpValue: PDouble;
  protected
    function GetVarIndex(const AName: String): Integer;
    function GetVarType(AIndex: Integer): TFDDataType;
    function GetVarScope(AIndex: Integer): TFDExpressionScopeKind;
    function GetVarData(AIndex: Integer): Variant;
    ...........
  public
    constructor Create(AName: String; var AValue: Double);
  end;

{ TMyVariable }

constructor TMyVariable.Create(AName: String; var AValue: Double);
begin
  inherited Create;
  FName := AName;
  FpValue := @AValue;
end;

function TMyVariable.GetVarIndex(const AName: String): Integer;
begin
  if CompareText(AName, FName) = 0 then
    Result := 0
  else
    Result := -1;
end;

function TMyVariable.GetVarType(AIndex: Integer): TFDDataType;
begin
  if AIndex = 0 then
    Result := dtDouble
  else
    Result := dtUnknown;
end;

function TMyVariable.GetVarScope(AIndex: Integer): TFDExpressionScopeKind;
begin
  if AIndex = 0 then
    Result := ckConst
  else
    Result := ckUnknown;
end;

function TMyVariable.GetVarData(AIndex: Integer): Variant;
begin
  if AIndex = 0 then
    Result := FpValue^
  else
    Result := Null;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  d: Double;
  oDS: IFDStanExpressionDataSource;
  oParser: IFDStanExpressionParser;
  oEval: IFDStanExpressionEvaluator;
begin
  oDS := TMyVariable.Create('x', d);

  FDCreateInterface(IFDStanExpressionParser, oParser);
  oEval := oParser.Prepare(oDS, '(2*x)+cos(sin(90)+10)', [], [poDefaultExpr], '');

  d := 1.2;
  ShowMessage(oEval.Evaluate);

  d := 3.4;
  ShowMessage(oEval.Evaluate);
end;

Samples