anchor.diff:      FFieldName : string;
       FFilterOperator : TmFilterOperator;
       FValue : Variant;
  +
  +    FValuesAsStrings : TStringList;
  +    FValuesDictionary: TmStringDictionary;
  +    procedure SetValue(AValue: Variant);
     public
       constructor Create;
       destructor Destroy; override;
   
  -    function GetFormattedValue : Variant;
  +    function Evaluate (aActualValue : Variant) : boolean;
  +    procedure CopyFrom (aSource : TmFilter);
  +
  +    function GetFormattedValueForSQL : Variant;
   
       property FieldName : string read FFieldName write FFieldName;
       property FilterOperator : TmFilterOperator read FFilterOperator write FFilterOperator;
  -    property Value : Variant read FValue write FValue;
  +    property Value : Variant read FValue write SetValue;
     end;
   
   
  
positive.code: interface
  
  uses
    Contnrs, Variants;
  
  type
    TmFilterOperator = (foUnknown, foEq, foGtOrEq, foLtOrEq, foLike, foNotEq, foStartWith, foEndWith);
  
    { TmFilter }
  
  
negative.code:   inherited Destroy;
  end;
  
  function TmFilter.Evaluate(aActualValue: Variant): boolean;
  var
    rl : TVariantRelationship;
    str, strF : string;
    i : integer;
  begin
    case Self.FilterOperator of
      foUnknown:
        Result := false;
      foEq:
        Result := (VarCompareValue(aActualValue, FValue) = vrEqual);
      foNotEq:
        Result := (VarCompareValue(aActualValue, FValue) = vrNotEqual);
      foGtOrEq:
        begin
          rl := VarCompareValue(aActualValue, FValue);
          Result := (rl = vrEqual) or (rl = vrGreaterThan);
        end;
      foLtOrEq:
        begin
          rl := VarCompareValue(aActualValue, FValue);
          Result := (rl = vrEqual) or (rl = vrLessThan);
        end;
      foLike:
        begin
          if not VarIsNull(FValue) then
          begin
            str := lowercase(VarToStr(FValue));
            strF := lowercase(VarToStr(aActualValue));
            Result := (Pos(strF, str) > 0);
          end
          else
            Result := false;
        end;
      foStartWith:
        begin
          if not VarIsNull(FValue) then
          begin
            str := lowercase(VarToStr(FValue));
            strF := lowercase(VarToStr(aActualValue));
            Result := (Pos(strF, str) = 1);
          end
          else
            Result := false;
        end;
      foEndWith:
        begin
          if not VarIsNull(FValue) then
          begin
            str := lowercase(VarToStr(FValue));
            strF := lowercase(VarToStr(aActualValue));
            Result := ((Pos(strF, str) - 1 + Length(strF)) = Length(str));
          end
          else
            Result := false;
        end;
      foIn:
        begin
          if not Assigned(FValuesAsStrings) then
          begin
            FValuesAsStrings := TStringList.Create;
            FValuesDictionary := TmStringDictionary.Create();
  
            ConvertVariantToStringList(aActualValue, FValuesAsStrings);
            for i := 0 to FValuesAsStrings.Count - 1 do
            begin
              str := lowercase(FValuesAsStrings.Strings[i]);
              if FValuesDictionary.Find(str) = nil then
                FValuesDictionary.Add(str, FValuesAsStrings); // FValuesAsString is just a placeholder, to be able to check return value of find as nil
            end;
          end;
          Result := FValuesDictionary.Find(lowercase(VarToStr(FValue))) <> nil;
        end;
    end;
  end;
  
  procedure TmFilter.CopyFrom(aSource: TmFilter);
  begin
    Self.FFieldName := aSource.FieldName;
    Self.FFilterOperator := aSource.FFilterOperator;
    Self.FValue := aSource.FValue;
  end;
  
  function TmFilter.GetFormattedValueForSQL: Variant;
  begin
    if not VarIsNull(FValue) then
    begin
  