* The bookmarkdata in a delete-update buffer now points to the old, deleted, record which is not deleted immediately anymore. Because else GetUpdateBuffer can not find the update-buffer from a deleted record

* Delete-update buffers now has an extra bookmark (NextBookmarkData) to store the next record in the dataset
 * Thus re-linking update buffers of records that are going to be deleted, is not necessary anymore
 * GetRecordUpdateBuffer now looks for update-buffers linked to BookmarkData, and for those linked to NextBookmarkdata only when asked
 * The commented-out resync in ApplyUpdates is replaced by a call to GetRecord. The goal is to synchronise the ActiveBuffer of TDataset with the CurrentBuffer of the TBufDataset.

git-svn-id: trunk@12365 -
This commit is contained in:
joost 2008-12-14 21:36:21 +00:00
parent 47ba5b19ec
commit 97ef7c31c7

View File

@ -73,13 +73,13 @@ type
- Is -1 if the update has canceled out. For example: a appended record has been deleted again - Is -1 if the update has canceled out. For example: a appended record has been deleted again
- If UpdateKind is ukInsert it contains a bookmark to the new created record - If UpdateKind is ukInsert it contains a bookmark to the new created record
- If UpdateKind is ukModify it contains a bookmark to the record with the new data - If UpdateKind is ukModify it contains a bookmark to the record with the new data
- If UpdateKind is ukDelete it contains a bookmark to the record just after the deleted record - If UpdateKind is ukDelete it contains a bookmark to the deleted record (ie: the record is still there)
} }
BookmarkData : TBufBookmark; BookmarkData : TBufBookmark;
{ DelBookMarkData: { NextBookMarkData:
- If UpdateKind is ukDelete it contains a bookmark to the deleted record, before it got deleted - If UpdateKind is ukDelete it contains a bookmark to the record just after the deleted record
} }
DelBookmarkData : TBufBookmark; NextBookmarkData : TBufBookmark;
{ OldValuesBuffer: { OldValuesBuffer:
- If UpdateKind is ukModify it contains a record-buffer which contains the old data - If UpdateKind is ukModify it contains a record-buffer which contains the old data
- If UpdateKind is ukDelete it contains a record-buffer with the data of the deleted record - If UpdateKind is ukDelete it contains a record-buffer with the data of the deleted record
@ -386,8 +386,8 @@ type
function GetIndexName: String; function GetIndexName: String;
function LoadBuffer(Buffer : PChar): TGetResult; function LoadBuffer(Buffer : PChar): TGetResult;
function GetFieldSize(FieldDef : TFieldDef) : longint; function GetFieldSize(FieldDef : TFieldDef) : longint;
function GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false) : boolean; function GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludePrior : boolean = false; AFindNext : boolean = false) : boolean;
function GetRecordUpdateBufferCached(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false) : boolean; function GetRecordUpdateBufferCached(const ABookmark : TBufBookmark; IncludePrior : boolean = false) : boolean;
function GetActiveRecordUpdateBuffer : boolean; function GetActiveRecordUpdateBuffer : boolean;
procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec); procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
procedure SetIndexFieldNames(const AValue: String); procedure SetIndexFieldNames(const AValue: String);
@ -1473,7 +1473,7 @@ begin
{$ENDIF} {$ENDIF}
end; end;
function TBufDataset.GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false): boolean; function TBufDataset.GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludePrior : boolean = false; AFindNext : boolean = false): boolean;
var x : integer; var x : integer;
StartBuf : integer; StartBuf : integer;
@ -1485,8 +1485,8 @@ begin
StartBuf := 0; StartBuf := 0;
Result := False; Result := False;
for x := StartBuf to high(FUpdateBuffer) do for x := StartBuf to high(FUpdateBuffer) do
if FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].BookmarkData,@ABookmark) and if FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].BookmarkData,@ABookmark) or
((FUpdateBuffer[x].UpdateKind<>ukDelete) or IncludeDeleted) then // The Bookmarkdata of a deleted record does not contain the deleted record, but the record thereafter (IncludePrior and (FUpdateBuffer[x].UpdateKind=ukDelete) and FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].NextBookmarkData,@ABookmark)) then
begin begin
FCurrentUpdateBuffer := x; FCurrentUpdateBuffer := x;
Result := True; Result := True;
@ -1495,15 +1495,15 @@ begin
end; end;
function TBufDataset.GetRecordUpdateBufferCached(const ABookmark: TBufBookmark; function TBufDataset.GetRecordUpdateBufferCached(const ABookmark: TBufBookmark;
IncludeDeleted: boolean): boolean; IncludePrior: boolean): boolean;
begin begin
// if the current update buffer complies, immediately return true // if the current update buffer complies, immediately return true
if (FCurrentUpdateBuffer < length(FUpdateBuffer)) and if (FCurrentUpdateBuffer < length(FUpdateBuffer)) and (
(FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark)) and FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark) or
((FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind<>ukDelete) or IncludeDeleted) then (IncludePrior and (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind=ukDelete) and FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].NextBookmarkData,@ABookmark))) then
Result := True Result := True
else else
Result := GetRecordUpdateBuffer(ABookmark,IncludeDeleted); Result := GetRecordUpdateBuffer(ABookmark,IncludePrior);
end; end;
function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult; function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
@ -1662,15 +1662,12 @@ end;
procedure TBufDataset.InternalDelete; procedure TBufDataset.InternalDelete;
var i : Integer; var i : Integer;
StartInd : Integer; StartInd : Integer;
RemRecBuf : Pchar;
RemRec : pointer; RemRec : pointer;
RemRecBookmrk : TBufBookmark; RemRecBookmrk : TBufBookmark;
TempUpdBuf: TRecUpdateBuffer;
begin begin
InternalSetToRecord(ActiveBuffer); InternalSetToRecord(ActiveBuffer);
// Remove the record from all active indexes // Remove the record from all active indexes
FCurrentIndex.StoreCurrentRecIntoBookmark(@RemRecBookmrk); FCurrentIndex.StoreCurrentRecIntoBookmark(@RemRecBookmrk);
RemRecBuf:=FCurrentIndex.GetCurrentRecord;
RemRec := FCurrentIndex.CurrentBuffer; RemRec := FCurrentIndex.CurrentBuffer;
FIndexes[0].RemoveRecordFromIndex(RemRecBookmrk); FIndexes[0].RemoveRecordFromIndex(RemRecBookmrk);
if FCurrentIndex=FIndexes[1] then StartInd := 1 else StartInd := 2; if FCurrentIndex=FIndexes[1] then StartInd := 1 else StartInd := 2;
@ -1684,40 +1681,16 @@ begin
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer; FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize); move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
FreeRecordBuffer(RemRecBuf);
end end
else //with FIndexes[0] do else //with FIndexes[0] do
begin begin
FreeRecordBuffer(RemRecBuf);
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil; //this 'disables' the updatebuffer FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil; //this 'disables' the updatebuffer
end; end;
FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData); FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].NextBookmarkData);
FUpdateBuffer[FCurrentUpdateBuffer].DelBookmarkData := RemRecBookmrk; FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData := RemRecBookmrk;
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukDelete; FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukDelete;
// Search for update-buffers which are linked to the deleted record and re-link
// them to the current record.
if GetRecordUpdateBuffer(RemRecBookmrk,True,False) then
begin
repeat
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukDelete then
begin
// If one of the update-buffers, linked to the deleted record, is a delete
// then disable the old update-buffer and create a new one. Such that the
// position of the records stays the samein case of a cancelupdates or
// something similar
TempUpdBuf := FUpdateBuffer[FCurrentUpdateBuffer];
move(FUpdateBuffer[FCurrentUpdateBuffer+1],FUpdateBuffer[FCurrentUpdateBuffer],((length(FUpdateBuffer)-FCurrentUpdateBuffer))*Sizeof(TRecUpdateBuffer));
dec(FCurrentUpdateBuffer);
FCurrentIndex.StoreCurrentRecIntoBookmark(@TempUpdBuf.BookmarkData);
FUpdateBuffer[length(FUpdateBuffer)-1] := TempUpdBuf;
end
else
FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
until not GetRecordUpdateBuffer(RemRecBookmrk,True,True)
end;
dec(FBRecordCount); dec(FBRecordCount);
end; end;
@ -1735,6 +1708,7 @@ var StoreRecBM : TBufBookmark;
TmpBuf : PChar; TmpBuf : PChar;
StoreUpdBuf : integer; StoreUpdBuf : integer;
Bm : TBufBookmark; Bm : TBufBookmark;
x : Integer;
begin begin
with AUpdBuffer do if assigned(BookmarkData.BookmarkData) then // this is used to exclude buffers which are already handled with AUpdBuffer do if assigned(BookmarkData.BookmarkData) then // this is used to exclude buffers which are already handled
begin begin
@ -1746,10 +1720,16 @@ var StoreRecBM : TBufBookmark;
end end
else if (UpdateKind = ukDelete) and (assigned(OldValuesBuffer)) then else if (UpdateKind = ukDelete) and (assigned(OldValuesBuffer)) then
begin begin
FCurrentIndex.GotoBookmark(@BookmarkData); FCurrentIndex.GotoBookmark(@NextBookmarkData);
FCurrentIndex.InsertRecordBeforeCurrentRecord(IntAllocRecordBuffer); FCurrentIndex.InsertRecordBeforeCurrentRecord(PChar(BookmarkData.BookmarkData));
FCurrentIndex.ScrollBackward; FCurrentIndex.ScrollBackward;
move(pchar(OldValuesBuffer)^,pchar(FCurrentIndex.CurrentBuffer)^,FRecordSize); move(pchar(OldValuesBuffer)^,pchar(FCurrentIndex.CurrentBuffer)^,FRecordSize);
{ for x := length(FUpdateBuffer)-1 downto 0 do
begin
if (FUpdateBuffer[x].UpdateKind=ukDelete) and FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].NextBookmarkData,@BookmarkData) then
CancelUpdBuffer(FUpdateBuffer[x]);
end;}
FreeRecordBuffer(OldValuesBuffer); FreeRecordBuffer(OldValuesBuffer);
inc(FBRecordCount); inc(FBRecordCount);
end end
@ -1844,8 +1824,8 @@ begin
if not ((FUpdateBuffer[r].UpdateKind=ukDelete) and not (assigned(FUpdateBuffer[r].OldValuesBuffer))) then if not ((FUpdateBuffer[r].UpdateKind=ukDelete) and not (assigned(FUpdateBuffer[r].OldValuesBuffer))) then
begin begin
FCurrentIndex.GotoBookmark(@FUpdateBuffer[r].BookmarkData); FCurrentIndex.GotoBookmark(@FUpdateBuffer[r].BookmarkData);
// Joost: I do not see the use of this resync? // Synchronise the Currentbuffer to the ActiveBuffer
//Resync([rmExact,rmCenter]); GetRecord(ActiveBuffer,gmCurrent,True);
Response := rrApply; Response := rrApply;
try try
ApplyRecUpdate(FUpdateBuffer[r].UpdateKind); ApplyRecUpdate(FUpdateBuffer[r].UpdateKind);
@ -1872,6 +1852,8 @@ begin
if response in [rrApply, rrIgnore] then if response in [rrApply, rrIgnore] then
begin begin
FreeRecordBuffer(FUpdateBuffer[r].OldValuesBuffer); FreeRecordBuffer(FUpdateBuffer[r].OldValuesBuffer);
if FUpdateBuffer[r].UpdateKind = ukDelete then
FreeRecordBuffer(PChar(FUpdateBuffer[r].BookmarkData.BookmarkData));
FUpdateBuffer[r].BookmarkData.BookmarkData := nil; FUpdateBuffer[r].BookmarkData.BookmarkData := nil;
end end
end; end;
@ -2309,9 +2291,6 @@ procedure TBufDataset.GetDatasetPacket(AWriter: TDataPacketReader);
end; end;
procedure HandleUpdateBuffersFromRecord(ARecBookmark : TBufBookmark; var ARowState: TRowState); procedure HandleUpdateBuffersFromRecord(ARecBookmark : TBufBookmark; var ARowState: TRowState);
var
StoreUpdBuf : integer;
ADumRowstate : TRowState;
begin begin
if GetRecordUpdateBuffer(ARecBookmark,True) then if GetRecordUpdateBuffer(ARecBookmark,True) then
begin begin
@ -2330,7 +2309,6 @@ var ScrollResult : TGetResult;
ABookMark : PBufBookmark; ABookMark : PBufBookmark;
ATBookmark : TBufBookmark; ATBookmark : TBufBookmark;
RowState : TRowState; RowState : TRowState;
EntryNr : integer;
begin begin
FDatasetReader := AWriter; FDatasetReader := AWriter;