The process fails When we search with more than one field and the index used is partially compatible and the record to be found is the current or the first one.
I've seen that the search procedure is made in two blocks:
- The first block executes the whole search if the search is fully compatible with the index;
- If there is no index or the index is fully incompatible, the second block executes the whole search;
- However, when the index is partially compatible, the first block executes it until it's possible, leaving the rest to the second block;
There is a fix to this problem attached to copy of this message sent by e-mail. This fix removes the need of finding the dataset in BOF for the second block.
This fix also solves the incoherence between the Locate and LocateEx methods. The LocateEx method with the lxNext parameter starts the search from the actual record, as documented.
Source code to test:
Code: Select all
program LocateBug;
uses
Forms, StdCtrls, DB, MemDS, VirtualTable, DBGrids, Variants;
var
Frm: TForm;
Lbl: TCustomLabel;
DBGrd: TDBGrid;
DtSrc: TDataSource;
VrtTbl: TVirtualTable;
Btn: TButton;
type
TLabelHelper = class helper for TCustomLabel
procedure AddLog(S: string);
end;
procedure TLabelHelper.AddLog(S: string);
begin
if Caption = '' then
Self.Caption := S
else
Self.Caption := Self.Caption + #13#10 + S;
end;
type
TTeste = class helper for TForm
procedure Test(Sernder: TObject);
end;
procedure TTeste.Test(Sernder: TObject);
var
V: Variant;
procedure DoTest(const Description, IndexFields: string);
begin
Lbl.AddLog(Description);
VrtTbl.IndexFieldNames := IndexFields;
if VrtTbl.Locate('Codigo;Nome', V, []) then
Lbl.AddLog('Ok')
else
Lbl.AddLog('Fail');
end;
begin
V := VarArrayOf([1, 'Abadia']);
Lbl.Caption := 'Abadia';
DoTest('*** Without index', '');
DoTest('*** With patial index', 'Codigo');
DoTest('*** With full compatible index', 'Codigo;Nome');
DoTest('*** With full incompatible index', 'Funcao');
V := VarArrayOf([2, 'Gustavo']);
Lbl.AddLog('Gustavo');
DoTest('*** Without index', '');
DoTest('*** With patial index', 'Codigo');
DoTest('*** With full compatible index', 'Codigo;Nome');
DoTest('*** With full incompatible index', 'Funcao');
end;
begin
Application.Initialize;
Application.CreateForm(TForm, Frm);
Frm.Caption := 'Locate and LocateEx Bug';
Frm.ClientHeight := 430;
Frm.ClientWidth := 426;
VrtTbl := TVirtualTable.Create(Frm);
VrtTbl.FieldDefs.Add('Codigo', ftInteger);
VrtTbl.FieldDefs.Add('Nome', ftString, 50);
VrtTbl.FieldDefs.Add('Funcao', ftString, 50);
VrtTbl.Active := True;
VrtTbl.AppendRecord([1, 'Abadia', 'Delphi Programmer']);
VrtTbl.AppendRecord([2, 'Gustavo', 'External Support']);
VrtTbl.AppendRecord([3, 'Matheus', 'Java Programmer']);
VrtTbl.AppendRecord([4, 'Roberto', 'Internal Support']);
DtSrc := TDataSource.Create(Frm);
DtSrc.DataSet := VrtTbl;
Lbl := TLabel.Create(Frm);
Lbl.Parent := Frm;
Lbl.Left := 96;
Lbl.Top := 147;
Lbl.Width := 313;
Lbl.Height := 270;
TLabel(Lbl).AutoSize := False;
DBGrd := TDBGrid.Create(Frm);
DBGrd.Parent := Frm;
DBGrd.Left := 8;
DBGrd.Top := 16;
DBGrd.Width := 401;
DBGrd.Height := 120;
DBGrd.Anchors := [akLeft, akTop, akRight];
DBGrd.DataSource := DtSrc;
Btn := TButton.Create(Frm);
Btn.Parent := Frm;
Btn.Left := 8;
Btn.Top := 142;
Btn.Width := 75;
Btn.Height := 25;
Btn.Caption := 'Test';
Btn.OnClick := Frm.Test;
Application.Run;
end.