TDBAdvGrid ERROR: AV When the active row is the last one of the dataset

There is a BUG(AccessViolation error) with this component.
It happens only if the selected row of the grid is at the last record of the dataset

Here is a simple source that demonstrates the AV :

unit Unit9;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AdvUtil, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.UI.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async,
FireDAC.Phys, FireDAC.Phys.FB, FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait, FireDAC.DApt, FireDAC.Comp.Client, Data.DB, FireDAC.Comp.DataSet, Vcl.Grids, AdvObj, BaseGrid, AdvGrid, DBAdvGrid, Vcl.StdCtrls, Vcl.ExtCtrls;

type
TForm9 = class(TForm)
DBAdvGrid1: TDBAdvGrid;
DataSource1: TDataSource;
FDMemTable1: TFDMemTable;
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
FDTable1: TFDTable;
Label1: TLabel;
CheckBox1: TCheckBox;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FilterID:Integer;
public
{ Public declarations }
end;

var
Form9: TForm9;

implementation

{$R *.dfm}

procedure TForm9.Button1Click(Sender: TObject);
begin
FDConnection1.Connected:=True;
FDQuery1.Open();
FilterID:=1;
end;

procedure TForm9.Button2Click(Sender: TObject);
Var IC:Integer;
begin
FDTAble1.DisableControls;
if Not FDTable1.Active Then FDTable1.Open();
FDTable1.Filtered:=False;
// Change the filter according to your table fields, it does not matter
Case FilterID of
1:Begin FDTAble1.Filter:='(GOdina=2025)And(Period=5)And(Vid='+FilterID.ToString+')'; FilterID:=2; End;
2:Begin FDTAble1.Filter:='(GOdina=2025)And(Period=5)And(Vid='+FilterID.ToString+')'; FilterID:=1; End;
End;

FDTable1.filtered:=true;

DBAdvGrid1.Columns.Clear;
With DBAdvGrid1.Columns.Add do width:=15;

For Ic:=0 to FDTable1.FieldCount-1 Do
With DBAdvGrid1.Columns.Add do
Begin
FieldName:= FDTable1.Fields[ic].FieldName;
Field:=FDTable1.Fields[Ic];
End;

FDTable1.EnableControls;

Label1.Caption:='Record count: '+FDTable1.RecordCount.ToString;

Case CheckBox1.Checked of
True:DBAdvGrid1.Row:=FDTable1.RecordCount; // This way you hit the AV
False:DBAdvGrid1.Row:=1; // This way everything is fine
End;

end;

end.

I tried to reproduce this with demo Demo\DBAdvGrid\ADOSelection by adding the code:

  ADOTable1.Filter := 'Brand LIKE ''FERRARI''';
  ADOTable1.Filtered := true;
  DBAdvGrid1.Row := ADOTable1.RecordCount;

but this works as expected.

Please make sure you use the latest version of the component and if the problem persists, modify demo and provide it so we can reproduce this here.

Hello, Bruno!
Yes, it is the latest release TDBAdvGrid v. 2.8.3.8 / Delphi 12.3 build 29.0.55362.2017
The scenario is that when you apply different filters and have to show different columns on each filter, so you have to clear the columns and populate them again every time(click/button).

Please prepare a sample or modify one of the demos and send a sample source project + steps to reproduce.

DemoSource.zip (3.2 MB)
I'm sending demo source with demo data in the directory win32\debug so the exe file can find it.

  1. Run the source
  2. Press the button few times
  3. Check the checkbox
  4. Press the button again few times
  5. Now you have to see the AV

We could reproduce this but it looks to be a very strange problem and we could not yet locate it.
Two workarounds for now:

procedure TForm9.Button2Click(Sender: TObject);
Var
  IC:Integer;
begin
  FDMemTable1.First;
  FDMemTable1.DisableControls;
  FDMemTable1.Filtered:=False;

  case FilterID of
  1:Begin FDMemTable1.Filter:='(GOdina=2025)And(Period=5)And(Vid=1)'; FilterID:=2; End;
  2:Begin FDMemTAble1.Filter:='(GOdina=2025)And(Period=5)And(Vid=2)'; FilterID:=1; End;
  End;

  FDMemTable1.filtered:=true;

  DBAdvGrid1.Columns.Clear;
  With DBAdvGrid1.Columns.Add do width:=15;

  For Ic:=0 to FDMemTable1.FieldCount-1 Do
    DBAdvGrid1.Columns.Add.Field:=FDMemTable1.Fields[Ic];


  FDMemTable1.EnableControls;

  Label1.Caption:='Record count: '+FDMemTable1.RecordCount.ToString;

  Case CheckBox1.Checked of
  True:FDMemTable1.Last;
  False:FDMemTable1.First;
  End;
end;

or

procedure TForm9.Button2Click(Sender: TObject);
Var
  IC:Integer;
begin
  FDMemTable1.DisableControls;
  FDMemTable1.Filtered:=False;

  case FilterID of
  1:Begin FDMemTable1.Filter:='(GOdina=2025)And(Period=5)And(Vid=1)'; FilterID:=2; End;
  2:Begin FDMemTAble1.Filter:='(GOdina=2025)And(Period=5)And(Vid=2)'; FilterID:=1; End;
  End;

  DBAdvGrid1.Columns.Clear;
  With DBAdvGrid1.Columns.Add do width:=15;

  For Ic:=0 to FDMemTable1.FieldCount-1 Do
    DBAdvGrid1.Columns.Add.Field:=FDMemTable1.Fields[Ic];

  FDMemTable1.filtered:=true;

  FDMemTable1.EnableControls;

  Label1.Caption:='Record count: '+FDMemTable1.RecordCount.ToString;

  Case CheckBox1.Checked of
  True:FDMemTable1.Last;
  False:FDMemTable1.First;
  End;
end;

Hello, Bruno!
Thank you for the feedback.
I have found a workaround similar to yours, but it was more important to report the issue so that it could be fixed.
I think it appeared after we moved to D12, there was no such issue before.

I could also reproduce it in older Delphi versions, so I'll keep investigating.
It seems some strange interference due to changes in the dataset caused by filtering, even when DisableControls was called.

1 Like