unit uFireDacHelper;

interface

uses
  System.SysUtils, FireDAC.Comp.DataSet, FireDAC.Comp.Client;

type
  TFDQuerySortType = (stNone, stAscending, stDescending);

  TFDDataSetHelper = class helper for TFDDataSet
  private
    function GetSortedFields: string;
    procedure SetSortedFields(const Value: string);
    function GetSortType: TFDQuerySortType;
    procedure SetSortType(Value: TFDQuerySortType);
    function GetLinkedFields: string;
    procedure SetLinkedFields(const Value: string);
  public
    procedure Prepare; // Empty method to override and prevent parameter type exceptions
    property SortedFields: string read GetSortedFields write SetSortedFields;
    property SortType: TFDQuerySortType read GetSortType write SetSortType;
    property LinkedFields: string read GetLinkedFields write SetLinkedFields;
  end;

  TFDConnectionHelper = class helper for TFDConnection
  public
    procedure ExecuteDirect(const ASQL: string);
    procedure Disconnect;
  end;

implementation

{ TFDDataSetHelper }

procedure TFDDataSetHelper.Prepare;
begin
  // Do nothing. FireDAC handles preparation automatically on Open / ExecSQL
  // after parameter types are resolved, preventing EDatabaseError with parameter datatypes.
end;

function TFDDataSetHelper.GetSortedFields: string;
var
  S: string;
  P: Integer;
begin
  S := IndexFieldNames;
  P := Pos(':', S);
  if P > 0 then
    Result := Copy(S, 1, P - 1)
  else
    Result := S;
end;

procedure TFDDataSetHelper.SetSortedFields(const Value: string);
begin
  if IndexFieldNames <> Value then
    IndexFieldNames := Value;
end;

function TFDDataSetHelper.GetSortType: TFDQuerySortType;
begin
  if Pos(':D', IndexFieldNames) > 0 then
    Result := stDescending
  else if IndexFieldNames <> '' then
    Result := stAscending
  else
    Result := stNone;
end;

procedure TFDDataSetHelper.SetSortType(Value: TFDQuerySortType);
var
  F: string;
begin
  F := GetSortedFields;
  if F <> '' then
  begin
    if Value = stDescending then
      IndexFieldNames := F + ':D'
    else
      IndexFieldNames := F;
  end;
end;

function TFDDataSetHelper.GetLinkedFields: string;
begin
  Result := IndexFieldNames;
end;

procedure TFDDataSetHelper.SetLinkedFields(const Value: string);
begin
  IndexFieldNames := Value;
end;

{ TFDConnectionHelper }

procedure TFDConnectionHelper.ExecuteDirect(const ASQL: string);
begin
  ExecSQL(ASQL);
end;

procedure TFDConnectionHelper.Disconnect;
begin
  Close;
end;

end.
