Browse Source

* 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 -

joost 16 years ago
parent
commit
97ef7c31c7
1 changed files with 29 additions and 51 deletions
  1. 29 51
      packages/fcl-db/src/base/bufdataset.pas

+ 29 - 51
packages/fcl-db/src/base/bufdataset.pas

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