mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 01:19:07 +02:00
fcl-db: bufdataset: when new record is inserted or existing edited and some sorted index is presented record is moved to proper position in index. (introduces OrderCurrentRecord method). Small drawback is than in case of inserting record new record is first inserted before current record and then moved to proper position.(but it takes only few memory operations in current implementation).
Bug #23465 git-svn-id: trunk@23592 -
This commit is contained in:
parent
5a81601565
commit
1b9842c33a
@ -161,14 +161,14 @@ type
|
||||
// Inserts a record before the current record, or if the record is sorted,
|
||||
// inserts it in the proper position
|
||||
procedure InsertRecordBeforeCurrentRecord(Const ARecord : TRecordBuffer); virtual; abstract;
|
||||
procedure OrderCurrentRecord; virtual; abstract;
|
||||
procedure EndUpdate; virtual; abstract;
|
||||
|
||||
procedure RemoveRecordFromIndex(const ABookmark : TBufBookmark); virtual; abstract;
|
||||
|
||||
|
||||
function CompareBookmarks(const ABookmark1, ABookmark2 : PBufBookmark) : boolean; virtual;
|
||||
Function GetRecNo(const ABookmark : PBufBookmark) : integer; virtual; abstract;
|
||||
|
||||
|
||||
property SpareRecord : TRecordBuffer read GetSpareRecord;
|
||||
property SpareBuffer : TRecordBuffer read GetSpareBuffer;
|
||||
property CurrentRecord : TRecordBuffer read GetCurrentRecord;
|
||||
@ -228,6 +228,7 @@ type
|
||||
procedure BeginUpdate; override;
|
||||
procedure AddRecord; override;
|
||||
procedure InsertRecordBeforeCurrentRecord(Const ARecord : TRecordBuffer); override;
|
||||
procedure OrderCurrentRecord; override;
|
||||
procedure EndUpdate; override;
|
||||
end;
|
||||
|
||||
@ -273,6 +274,7 @@ type
|
||||
procedure BeginUpdate; override;
|
||||
procedure AddRecord; override;
|
||||
procedure InsertRecordBeforeCurrentRecord(Const ARecord : TRecordBuffer); override;
|
||||
procedure OrderCurrentRecord; override;
|
||||
procedure EndUpdate; override;
|
||||
end;
|
||||
|
||||
@ -1466,6 +1468,37 @@ begin
|
||||
ANewRecord[IndNr].next[IndNr].prior:=ANewRecord;
|
||||
end;
|
||||
|
||||
procedure TDoubleLinkedBufIndex.OrderCurrentRecord;
|
||||
var ARecord: PBufRecLinkItem;
|
||||
ABookmark: TBufBookmark;
|
||||
begin
|
||||
// all records except current are already sorted
|
||||
// check prior records
|
||||
ARecord := FCurrentRecBuf;
|
||||
repeat
|
||||
ARecord := ARecord[IndNr].prior;
|
||||
until not assigned(ARecord) or (IndexCompareRecords(ARecord, FCurrentRecBuf, DBCompareStruct) <= 0);
|
||||
if assigned(ARecord) then
|
||||
ARecord := ARecord[IndNr].next
|
||||
else
|
||||
ARecord := FFirstRecBuf;
|
||||
if ARecord = FCurrentRecBuf then
|
||||
begin
|
||||
// prior record is less equal than current
|
||||
// check next records
|
||||
repeat
|
||||
ARecord := ARecord[IndNr].next;
|
||||
until (ARecord=FLastRecBuf) or (IndexCompareRecords(ARecord, FCurrentRecBuf, DBCompareStruct) >= 0);
|
||||
if ARecord = FCurrentRecBuf[IndNr].next then
|
||||
Exit; // current record is on proper position
|
||||
end;
|
||||
StoreCurrentRecIntoBookmark(@ABookmark);
|
||||
RemoveRecordFromIndex(ABookmark);
|
||||
FCurrentRecBuf := ARecord;
|
||||
InsertRecordBeforeCurrentRecord(TRecordBuffer(ABookmark.BookmarkData));
|
||||
GotoBookmark(@ABookmark);
|
||||
end;
|
||||
|
||||
procedure TDoubleLinkedBufIndex.EndUpdate;
|
||||
begin
|
||||
FLastRecBuf[IndNr].next := FFirstRecBuf;
|
||||
@ -2242,18 +2275,14 @@ begin
|
||||
end;
|
||||
|
||||
// Link the newly created record buffer to the newly created TDataset record
|
||||
with ABookmark^ do
|
||||
begin
|
||||
FCurrentIndex.StoreCurrentRecIntoBookmark(@BookmarkData);
|
||||
BookmarkFlag := bfInserted;
|
||||
end;
|
||||
FCurrentIndex.StoreCurrentRecIntoBookmark(ABookmark);
|
||||
ABookmark^.BookmarkFlag := bfInserted;
|
||||
|
||||
inc(FBRecordCount);
|
||||
end
|
||||
else
|
||||
InternalSetToRecord(ActiveBuffer);
|
||||
|
||||
|
||||
// If there is no updatebuffer already, add one
|
||||
if not GetActiveRecordUpdateBuffer then
|
||||
begin
|
||||
@ -2281,6 +2310,11 @@ begin
|
||||
end;
|
||||
|
||||
move(ActiveBuffer^,FCurrentIndex.CurrentBuffer^,FRecordSize);
|
||||
|
||||
// new data are now in current record so reorder current record if needed
|
||||
for i := 1 to FIndexesCount-1 do
|
||||
if (i<>1) or (FIndexes[i]=FCurrentIndex) then
|
||||
FIndexes[i].OrderCurrentRecord;
|
||||
end;
|
||||
|
||||
procedure TCustomBufDataset.CalcRecordSize;
|
||||
@ -3683,6 +3717,11 @@ begin
|
||||
// Do nothing
|
||||
end;
|
||||
|
||||
procedure TUniDirectionalBufIndex.OrderCurrentRecord;
|
||||
begin
|
||||
// Do nothing
|
||||
end;
|
||||
|
||||
procedure TUniDirectionalBufIndex.EndUpdate;
|
||||
begin
|
||||
// Do nothing
|
||||
|
@ -2111,6 +2111,7 @@ procedure TTestBufDatasetDBBasics.TestIndexAppendRecord;
|
||||
var i: integer;
|
||||
LastValue: string;
|
||||
begin
|
||||
// start with empty dataset
|
||||
with DBConnector.GetNDataset(true,0) as TCustomBufDataset do
|
||||
begin
|
||||
MaxIndexesCount:=4;
|
||||
@ -2125,19 +2126,20 @@ begin
|
||||
// append data at end
|
||||
for i:=20 downto 0 do
|
||||
AppendRecord([i, inttostr(i)]);
|
||||
First;
|
||||
// insert data at begining
|
||||
IndexName:='';
|
||||
First;
|
||||
for i:=21 to 22 do
|
||||
InsertRecord([i, inttostr(i)]);
|
||||
|
||||
// ATM new records are not ordered as they are added ?
|
||||
// swith to index and check if records are ordered
|
||||
IndexName := 'testindex';
|
||||
LastValue := '';
|
||||
First;
|
||||
for i:=22 downto 0 do
|
||||
begin
|
||||
CheckEquals(23-i, RecNo, 'testindex.RecNo:');
|
||||
CheckEquals(inttostr(i), Fields[1].AsString, 'testindex.Fields[1].Value:');
|
||||
//CheckTrue(AnsiCompareStr(LastValue,Fields[1].AsString) < 0, 'testindex.LastValue>CurrValue');
|
||||
CheckTrue(AnsiCompareStr(LastValue,Fields[1].AsString) < 0, 'testindex.LastValue>=CurrValue');
|
||||
LastValue := Fields[1].AsString;
|
||||
Next;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user