|
@@ -76,6 +76,10 @@ type
|
|
|
- If UpdateKind is ukDelete it contains a bookmark to the record just after the deleted record
|
|
|
}
|
|
|
BookmarkData : TBufBookmark;
|
|
|
+{ DelBookMarkData:
|
|
|
+ - If UpdateKind is ukDelete it contains a bookmark to the deleted record, before it got deleted
|
|
|
+}
|
|
|
+ DelBookmarkData : 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
|
|
@@ -105,7 +109,6 @@ type
|
|
|
TBufIndex = class(TObject)
|
|
|
private
|
|
|
FDataset : TBufDataset;
|
|
|
-
|
|
|
protected
|
|
|
function GetBookmarkSize: integer; virtual; abstract;
|
|
|
function GetCurrentBuffer: Pointer; virtual; abstract;
|
|
@@ -306,22 +309,25 @@ type
|
|
|
TDatapacketReaderClass = class of TDatapacketReader;
|
|
|
TDataPacketReader = class(TObject)
|
|
|
FStream : TStream;
|
|
|
+ protected
|
|
|
+ class function RowStateToByte(const ARowState : TRowState) : byte;
|
|
|
+ class function ByteToRowState(const AByte : Byte) : TRowState;
|
|
|
public
|
|
|
constructor create(AStream : TStream); virtual;
|
|
|
|
|
|
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
|
|
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
|
|
- procedure GetRecordUpdState(var AIsUpdate,AAddRecordBuffer,AIsFirstEntry : boolean); virtual; abstract;
|
|
|
- procedure EndStoreRecord(const AChangeLog : TChangeLogEntryArr); virtual; abstract;
|
|
|
+ function GetRecordRowState(out AUpdOrder : Integer) : TRowState; virtual; abstract;
|
|
|
+ procedure EndStoreRecord; virtual; abstract;
|
|
|
function GetCurrentRecord : boolean; virtual; abstract;
|
|
|
procedure GotoNextRecord; virtual; abstract;
|
|
|
function GetCurrentElement : pointer; virtual; abstract;
|
|
|
procedure GotoElement(const AnElement : pointer); virtual; abstract;
|
|
|
procedure RestoreRecord(ADataset : TBufDataset); virtual; abstract;
|
|
|
- procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); virtual; abstract;
|
|
|
- procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); virtual; abstract;
|
|
|
- property Stream: TStream read FStream;
|
|
|
+ procedure StoreRecord(ADataset : TBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); virtual; abstract;
|
|
|
+ procedure InitLoadRecords; virtual; abstract;
|
|
|
class function RecognizeStream(AStream : TStream) : boolean; virtual; abstract;
|
|
|
+ property Stream: TStream read FStream;
|
|
|
end;
|
|
|
|
|
|
{ TFpcBinaryDatapacketReader }
|
|
@@ -330,16 +336,15 @@ type
|
|
|
public
|
|
|
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
|
|
|
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
|
|
|
- procedure GetRecordUpdState(var AIsUpdate, AAddRecordBuffer,
|
|
|
- AIsFirstEntry: boolean); override;
|
|
|
- procedure EndStoreRecord(const AChangeLog : TChangeLogEntryArr); override;
|
|
|
+ function GetRecordRowState(out AUpdOrder : Integer) : TRowState; override;
|
|
|
+ procedure EndStoreRecord; override;
|
|
|
function GetCurrentRecord : boolean; override;
|
|
|
procedure GotoNextRecord; override;
|
|
|
procedure GotoElement(const AnElement : pointer); override;
|
|
|
- procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); override;
|
|
|
+ procedure InitLoadRecords; override;
|
|
|
function GetCurrentElement: pointer; override;
|
|
|
procedure RestoreRecord(ADataset : TBufDataset); override;
|
|
|
- procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override;
|
|
|
+ procedure StoreRecord(ADataset : TBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); override;
|
|
|
class function RecognizeStream(AStream : TStream) : boolean; override;
|
|
|
end;
|
|
|
|
|
@@ -385,7 +390,7 @@ type
|
|
|
function GetIndexName: String;
|
|
|
function LoadBuffer(Buffer : PChar): TGetResult;
|
|
|
function GetFieldSize(FieldDef : TFieldDef) : longint;
|
|
|
- function GetRecordUpdateBuffer(const ABookmark : TBufBookmark) : boolean;
|
|
|
+ function GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false) : boolean;
|
|
|
function GetActiveRecordUpdateBuffer : boolean;
|
|
|
procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
|
|
|
procedure SetIndexFieldNames(const AValue: String);
|
|
@@ -395,7 +400,7 @@ type
|
|
|
function IntAllocRecordBuffer: PChar;
|
|
|
procedure DoFilterRecord(var Acceptable: Boolean);
|
|
|
procedure ParseFilter(const AFilter: string);
|
|
|
- procedure IntLoadFielddefsFromFile(const FileName: string);
|
|
|
+ procedure IntLoadFielddefsFromFile;
|
|
|
procedure IntLoadRecordsFromFile;
|
|
|
protected
|
|
|
procedure UpdateIndexDefs; override;
|
|
@@ -466,6 +471,7 @@ type
|
|
|
procedure LoadFromFile(AFileName: string = ''; Format: TDataPacketFormat = dfAny);
|
|
|
procedure SaveToFile(AFileName: string = ''; Format: TDataPacketFormat = dfBinary);
|
|
|
procedure CreateDataset;
|
|
|
+ function CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint; override;
|
|
|
|
|
|
property ChangeCount : Integer read GetChangeCount;
|
|
|
property MaxIndexesCount : Integer read FMaxIndexesCount write SetMaxIndexesCount;
|
|
@@ -913,7 +919,7 @@ begin
|
|
|
FFileStream := TFileStream.Create(FileName,fmOpenRead);
|
|
|
FDatasetReader := TFpcBinaryDatapacketReader.Create(FFileStream);
|
|
|
end;
|
|
|
- if assigned(FDatasetReader) then IntLoadFielddefsFromFile(FFileName);
|
|
|
+ if assigned(FDatasetReader) then IntLoadFielddefsFromFile;
|
|
|
CalcRecordSize;
|
|
|
|
|
|
FBRecordcount := 0;
|
|
@@ -1516,21 +1522,30 @@ begin
|
|
|
{$ENDIF}
|
|
|
end;
|
|
|
|
|
|
-function TBufDataset.GetRecordUpdateBuffer(const ABookmark: TBufBookmark): boolean;
|
|
|
+function TBufDataset.GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false): boolean;
|
|
|
|
|
|
-var x : integer;
|
|
|
+var x : integer;
|
|
|
+ StartBuf : integer;
|
|
|
|
|
|
begin
|
|
|
+ if AFindNext then
|
|
|
+ begin
|
|
|
+ inc(FCurrentUpdateBuffer);
|
|
|
+ StartBuf:=FCurrentUpdateBuffer;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ StartBuf := 0;
|
|
|
if (FCurrentUpdateBuffer >= length(FUpdateBuffer)) or not FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark) then
|
|
|
- for x := 0 to high(FUpdateBuffer) do
|
|
|
+ for x := StartBuf to high(FUpdateBuffer) do
|
|
|
if FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].BookmarkData,@ABookmark) and
|
|
|
- (FUpdateBuffer[x].UpdateKind<>ukDelete) then // The Bookmarkdata of a deleted record does not contain the deleted record, but the record thereafter
|
|
|
+ ((FUpdateBuffer[x].UpdateKind<>ukDelete) or IncludeDeleted) then // The Bookmarkdata of a deleted record does not contain the deleted record, but the record thereafter
|
|
|
begin
|
|
|
FCurrentUpdateBuffer := x;
|
|
|
break;
|
|
|
end;
|
|
|
Result := (FCurrentUpdateBuffer < length(FUpdateBuffer)) and
|
|
|
- (FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark));
|
|
|
+ (FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark)) and
|
|
|
+ ((FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind<>ukDelete) or IncludeDeleted) ;
|
|
|
end;
|
|
|
|
|
|
function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
|
|
@@ -1711,7 +1726,8 @@ begin
|
|
|
// may arise. The 'delete' is placed in the update-buffer before the actual delete
|
|
|
// took place. This can lead into troubles, because other updates can depend on
|
|
|
// the record still being available.
|
|
|
- if not GetActiveRecordUpdateBuffer or (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukModify) then
|
|
|
+ if not GetActiveRecordUpdateBuffer or
|
|
|
+ (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukModify) then
|
|
|
begin
|
|
|
FCurrentUpdateBuffer := length(FUpdateBuffer);
|
|
|
SetLength(FUpdateBuffer,FCurrentUpdateBuffer+1);
|
|
@@ -1719,15 +1735,15 @@ begin
|
|
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
|
|
|
move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
|
|
FreeRecordBuffer(RemRecBuf);
|
|
|
- FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
|
end
|
|
|
else //with FIndexes[0] do
|
|
|
begin
|
|
|
FreeRecordBuffer(RemRecBuf);
|
|
|
- FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
|
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
|
|
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil; //this 'disables' the updatebuffer
|
|
|
end;
|
|
|
+ FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
|
+ FUpdateBuffer[FCurrentUpdateBuffer].DelBookmarkData := RemRecBookmrk;
|
|
|
|
|
|
dec(FBRecordCount);
|
|
|
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukDelete;
|
|
@@ -2321,27 +2337,22 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TBufDataset.GetDatasetPacket(AWriter: TDataPacketReader);
|
|
|
-var i : integer;
|
|
|
- ScrollResult : TGetResult;
|
|
|
+var ScrollResult : TGetResult;
|
|
|
StoreDSState : TDataSetState;
|
|
|
ABookMark : PBufBookmark;
|
|
|
ATBookmark : TBufBookmark;
|
|
|
- ChangeLog : array of TChangeLogEntry;
|
|
|
-
|
|
|
-var RowState : TRowState;
|
|
|
- RecUpdBuf: integer;
|
|
|
- EntryNr : integer;
|
|
|
- ChangeLogStr : String;
|
|
|
+ RowState : TRowState;
|
|
|
+ EntryNr : integer;
|
|
|
+ StoreUpdBuf : integer;
|
|
|
+ RunNr : integer;
|
|
|
|
|
|
begin
|
|
|
FDatasetReader := AWriter;
|
|
|
try
|
|
|
-
|
|
|
- // CheckActive;
|
|
|
+ //CheckActive;
|
|
|
ABookMark:=@ATBookmark;
|
|
|
FDatasetReader.StoreFieldDefs(FieldDefs);
|
|
|
|
|
|
- SetLength(ChangeLog,length(FUpdateBuffer));
|
|
|
EntryNr:=1;
|
|
|
|
|
|
StoreDSState:=State;
|
|
@@ -2350,71 +2361,43 @@ begin
|
|
|
while ScrollResult=grOK do
|
|
|
begin
|
|
|
FCurrentIndex.StoreCurrentRecIntoBookmark(ABookmark);
|
|
|
- if GetRecordUpdateBuffer(ABookmark^) and (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukDelete) then
|
|
|
+ if GetRecordUpdateBuffer(ABookmark^,True) then
|
|
|
begin
|
|
|
- if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukInsert then
|
|
|
- begin
|
|
|
- RowState:=[rsvInserted];
|
|
|
- FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
|
- with ChangeLog[FCurrentUpdateBuffer] do
|
|
|
- begin
|
|
|
- OrigEntry:=0;
|
|
|
- NewEntry:=EntryNr;
|
|
|
- UpdateKind:=ukInsert;
|
|
|
- end;
|
|
|
- end
|
|
|
- else // This is always ukModified
|
|
|
- begin
|
|
|
- RowState:=[rsvOriginal];
|
|
|
- FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
|
|
- ChangeLog[FCurrentUpdateBuffer].OrigEntry:=EntryNr;
|
|
|
- end;
|
|
|
+ case FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind of
|
|
|
+ ukModify : begin
|
|
|
+ FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
|
|
+ FDatasetReader.StoreRecord(Self,[rsvOriginal],FCurrentUpdateBuffer);
|
|
|
+ RowState:=[rsvUpdated];
|
|
|
+ end;
|
|
|
+ ukDelete : begin
|
|
|
+ repeat
|
|
|
+ StoreUpdBuf := FCurrentUpdateBuffer;
|
|
|
+ RunNr := 0;
|
|
|
+
|
|
|
+ repeat
|
|
|
+ inc(RunNr);
|
|
|
+ Assert(FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind=ukDelete);
|
|
|
+ FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
|
|
+ FDatasetReader.StoreRecord(Self,[rsvDeleted],FCurrentUpdateBuffer);
|
|
|
+ RowState:=[];
|
|
|
+ until not GetRecordUpdateBuffer(FUpdateBuffer[FCurrentUpdateBuffer].DelBookmarkData,True,RunNr>1);
|
|
|
+
|
|
|
+ FCurrentUpdateBuffer:=StoreUpdBuf;
|
|
|
+ until not GetRecordUpdateBuffer(ABookmark^,True,True)
|
|
|
+ end;
|
|
|
+ end; { case }
|
|
|
end
|
|
|
else
|
|
|
- begin
|
|
|
- FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
|
RowState:=[];
|
|
|
- end;
|
|
|
+ FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
|
+ FDatasetReader.StoreRecord(Self,RowState,FCurrentUpdateBuffer);
|
|
|
|
|
|
- FDatasetReader.StoreRecord(Self,RowState);
|
|
|
inc(EntryNr);
|
|
|
ScrollResult:=FCurrentIndex.ScrollForward;
|
|
|
end;
|
|
|
-
|
|
|
- for RecUpdBuf:=0 to length(FUpdateBuffer)-1 do with FUpdateBuffer[RecUpdBuf] do
|
|
|
- begin
|
|
|
- if UpdateKind = ukDelete then
|
|
|
- begin
|
|
|
- RowState:=[rsvDeleted];
|
|
|
- FFilterBuffer:=FUpdateBuffer[RecUpdBuf].OldValuesBuffer;
|
|
|
- FDatasetReader.StoreRecord(Self, RowState);
|
|
|
- with ChangeLog[RecUpdBuf] do
|
|
|
- begin
|
|
|
- NewEntry:=EntryNr;
|
|
|
- UpdateKind:=ukDelete;
|
|
|
- end;
|
|
|
- inc(EntryNr);
|
|
|
- end
|
|
|
- else if UpdateKind = ukModify then
|
|
|
- begin
|
|
|
- RowState:=[rsvUpdated];
|
|
|
- FCurrentIndex.GotoBookmark(@BookmarkData);
|
|
|
- FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
|
- FDatasetReader.StoreRecord(Self, RowState);
|
|
|
- with ChangeLog[RecUpdBuf] do
|
|
|
- begin
|
|
|
- NewEntry:=EntryNr;
|
|
|
- UpdateKind:=ukModify;
|
|
|
- end;
|
|
|
- inc(EntryNr);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
RestoreState(StoreDSState);
|
|
|
|
|
|
- FDatasetReader.EndStoreRecord(ChangeLog);
|
|
|
- SetLength(ChangeLog,0);
|
|
|
-
|
|
|
+ FDatasetReader.EndStoreRecord;
|
|
|
finally
|
|
|
FDatasetReader := nil;
|
|
|
end;
|
|
@@ -2427,7 +2410,10 @@ begin
|
|
|
if GetRegisterDatapacketReader(AStream,format,APacketReaderReg) then
|
|
|
APacketReader := APacketReaderReg.ReaderClass.create(AStream)
|
|
|
else if TFpcBinaryDatapacketReader.RecognizeStream(AStream) then
|
|
|
+ begin
|
|
|
+ AStream.Seek(0,soFromBeginning);
|
|
|
APacketReader := TFpcBinaryDatapacketReader.create(AStream)
|
|
|
+ end
|
|
|
else
|
|
|
DatabaseError(SStreamNotRecognised);
|
|
|
try
|
|
@@ -2472,7 +2458,16 @@ begin
|
|
|
CreateFields;
|
|
|
end;
|
|
|
|
|
|
-procedure TBufDataset.IntLoadFielddefsFromFile(const FileName: string);
|
|
|
+function TBufDataset.CompareBookmarks(Bookmark1, Bookmark2: TBookmark
|
|
|
+ ): Longint;
|
|
|
+begin
|
|
|
+ if FCurrentIndex.CompareBookmarks(Bookmark1,Bookmark2) then
|
|
|
+ Result := 0
|
|
|
+ else
|
|
|
+ Result := -1;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TBufDataset.IntLoadFielddefsFromFile;
|
|
|
|
|
|
begin
|
|
|
FDatasetReader.LoadFielddefs(FieldDefs);
|
|
@@ -2481,44 +2476,71 @@ end;
|
|
|
|
|
|
procedure TBufDataset.IntLoadRecordsFromFile;
|
|
|
|
|
|
-
|
|
|
-var StoreState : TDataSetState;
|
|
|
- ChangeLog : TChangeLogEntryArr;
|
|
|
- ChangeLogStr : string;
|
|
|
- ChangeLogInfo : TChangeLogInfoArr;
|
|
|
- EntryNr : integer;
|
|
|
- i : integer;
|
|
|
- IsUpdate,
|
|
|
- AddRecordBuffer,
|
|
|
- IsFirstEntry : boolean;
|
|
|
+var StoreState : TDataSetState;
|
|
|
+ EntryNr : integer;
|
|
|
+ AddRecordBuffer : boolean;
|
|
|
+ ARowState : TRowState;
|
|
|
+ AUpdOrder : integer;
|
|
|
|
|
|
begin
|
|
|
- FDatasetReader.InitLoadRecords(ChangeLog);
|
|
|
+ FDatasetReader.InitLoadRecords;
|
|
|
EntryNr:=1;
|
|
|
StoreState:=SetTempState(dsFilter);
|
|
|
- SetLength(ChangeLogInfo,length(ChangeLog));
|
|
|
|
|
|
while FDatasetReader.GetCurrentRecord do
|
|
|
begin
|
|
|
- FDatasetReader.GetRecordUpdState(IsUpdate,AddRecordBuffer,IsFirstEntry);
|
|
|
-
|
|
|
- if IsUpdate then
|
|
|
+ ARowState := FDatasetReader.GetRecordRowState(AUpdOrder);
|
|
|
+ if rsvOriginal in ARowState then
|
|
|
begin
|
|
|
- if IsFirstEntry then
|
|
|
- begin
|
|
|
- for i := 0 to length(ChangeLog) -1 do
|
|
|
- if ChangeLog[i].OrigEntry=EntryNr then break;
|
|
|
- ChangeLogInfo[i].FirstChangeNode:=FDatasetReader.GetCurrentElement;
|
|
|
- end
|
|
|
+ if length(FUpdateBuffer) < (AUpdOrder+1) then
|
|
|
+ SetLength(FUpdateBuffer,AUpdOrder+1);
|
|
|
+
|
|
|
+ FCurrentUpdateBuffer:=AUpdOrder;
|
|
|
+
|
|
|
+ FFilterBuffer:=IntAllocRecordBuffer;
|
|
|
+ fillchar(FFilterBuffer^,FNullmaskSize,0);
|
|
|
+ FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := FFilterBuffer;
|
|
|
+ FDatasetReader.RestoreRecord(self);
|
|
|
+
|
|
|
+ FDatasetReader.GotoNextRecord;
|
|
|
+ if not FDatasetReader.GetCurrentRecord then
|
|
|
+ DatabaseError(SStreamNotRecognised);
|
|
|
+ ARowState := FDatasetReader.GetRecordRowState(AUpdOrder);
|
|
|
+ if rsvUpdated in ARowState then
|
|
|
+ FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:= ukModify
|
|
|
else
|
|
|
- begin
|
|
|
- for i := 0 to length(ChangeLog) -1 do
|
|
|
- if ChangeLog[i].NewEntry=EntryNr then break;
|
|
|
- ChangeLogInfo[i].SecondChangeNode:=FDatasetReader.GetCurrentElement;
|
|
|
- end;
|
|
|
+ DatabaseError(SStreamNotRecognised);
|
|
|
|
|
|
- FIndexes[0].StoreSpareRecIntoBookmark(@ChangeLogInfo[i].Bookmark);
|
|
|
- end;
|
|
|
+ FFilterBuffer:=FIndexes[0].SpareBuffer;
|
|
|
+ FIndexes[0].StoreSpareRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
|
+ fillchar(FFilterBuffer^,FNullmaskSize,0);
|
|
|
+
|
|
|
+ FDatasetReader.RestoreRecord(self);
|
|
|
+ FIndexes[0].AddRecord(IntAllocRecordBuffer);
|
|
|
+ inc(FBRecordCount);
|
|
|
+
|
|
|
+ AddRecordBuffer:=False;
|
|
|
+
|
|
|
+ end
|
|
|
+ else if rsvDeleted in ARowState then
|
|
|
+ begin
|
|
|
+ if length(FUpdateBuffer) < (AUpdOrder+1) then
|
|
|
+ SetLength(FUpdateBuffer,AUpdOrder+1);
|
|
|
+
|
|
|
+ FCurrentUpdateBuffer:=AUpdOrder;
|
|
|
+
|
|
|
+ FFilterBuffer:=IntAllocRecordBuffer;
|
|
|
+ fillchar(FFilterBuffer^,FNullmaskSize,0);
|
|
|
+ FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := FFilterBuffer;
|
|
|
+ FDatasetReader.RestoreRecord(self);
|
|
|
+
|
|
|
+ FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:= ukDelete;
|
|
|
+ FIndexes[0].StoreSpareRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
|
+
|
|
|
+ AddRecordBuffer:=False;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ AddRecordBuffer:=True;
|
|
|
|
|
|
if AddRecordBuffer then
|
|
|
begin
|
|
@@ -2534,35 +2556,6 @@ begin
|
|
|
inc(EntryNr);
|
|
|
end;
|
|
|
|
|
|
- // Iterate through the ChangeLog list and add modifications to he update buffer
|
|
|
- for i := 0 to length(ChangeLog)-1 do
|
|
|
- begin
|
|
|
- FCurrentUpdateBuffer:=Length(FUpdateBuffer);
|
|
|
- setlength(FUpdateBuffer,FCurrentUpdateBuffer+1);
|
|
|
- case ChangeLog[i].UpdateKind of
|
|
|
- ukDelete : begin
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukDelete;
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
|
- FDatasetReader.GotoElement(ChangeLogInfo[i].FirstChangeNode);
|
|
|
- FDatasetReader.RestoreRecord(self);
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer:=IntAllocRecordBuffer;
|
|
|
- move(findexes[0].SpareBuffer^,FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
|
|
- end;
|
|
|
- ukModify : begin
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukModify;
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
|
- FDatasetReader.GotoElement(ChangeLogInfo[i].SecondChangeNode);
|
|
|
- FDatasetReader.RestoreRecord(self);
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer:=IntAllocRecordBuffer;
|
|
|
- move(findexes[0].SpareBuffer^,FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
|
|
- end;
|
|
|
- ukInsert : begin
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukInsert;
|
|
|
- FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
|
- FDatasetReader.GotoElement(ChangeLogInfo[i].FirstChangeNode);
|
|
|
- end;
|
|
|
- end; {case}
|
|
|
- end;
|
|
|
RestoreState(StoreState);
|
|
|
FIndexes[0].SetToFirstRecord;
|
|
|
FAllPacketsFetched:=True;
|
|
@@ -2820,6 +2813,7 @@ end;
|
|
|
|
|
|
constructor TArrayBufIndex.Create(const ADataset: TBufDataset);
|
|
|
begin
|
|
|
+ Inherited create(ADataset);
|
|
|
FInitialBuffers:=10000;
|
|
|
FGrowBuffer:=1000;
|
|
|
end;
|
|
@@ -2993,6 +2987,27 @@ end;
|
|
|
|
|
|
{ TDataPacketReader }
|
|
|
|
|
|
+class function TDataPacketReader.RowStateToByte(const ARowState: TRowState
|
|
|
+ ): byte;
|
|
|
+var RowStateInt : Byte;
|
|
|
+begin
|
|
|
+ RowStateInt:=0;
|
|
|
+ if rsvOriginal in ARowState then RowStateInt := RowStateInt+1;
|
|
|
+ if rsvDeleted in ARowState then RowStateInt := RowStateInt+2;
|
|
|
+ if rsvInserted in ARowState then RowStateInt := RowStateInt+4;
|
|
|
+ if rsvUpdated in ARowState then RowStateInt := RowStateInt+8;
|
|
|
+ Result := RowStateInt;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TDataPacketReader.ByteToRowState(const AByte: Byte): TRowState;
|
|
|
+begin
|
|
|
+ result := [];
|
|
|
+ if (AByte and 1)=1 then Result := Result+[rsvOriginal];
|
|
|
+ if (AByte and 2)=2 then Result := Result+[rsvDeleted];
|
|
|
+ if (AByte and 4)=4 then Result := Result+[rsvInserted];
|
|
|
+ if (AByte and 8)=8 then Result := Result+[rsvUpdated];
|
|
|
+end;
|
|
|
+
|
|
|
constructor TDataPacketReader.create(AStream: TStream);
|
|
|
begin
|
|
|
FStream := AStream;
|
|
@@ -3044,17 +3059,20 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-procedure TFpcBinaryDatapacketReader.GetRecordUpdState(var AIsUpdate,
|
|
|
- AAddRecordBuffer, AIsFirstEntry: boolean);
|
|
|
+function TFpcBinaryDatapacketReader.GetRecordRowState(out AUpdOrder : Integer) : TRowState;
|
|
|
+var Buf : byte;
|
|
|
begin
|
|
|
- AIsUpdate:=False;
|
|
|
- AAddRecordBuffer:=True;
|
|
|
+ Stream.Read(Buf,1);
|
|
|
+ Result := ByteToRowState(Buf);
|
|
|
+ if Result<>[] then
|
|
|
+ Stream.ReadBuffer(AUpdOrder,sizeof(integer))
|
|
|
+ else
|
|
|
+ AUpdOrder := 0;
|
|
|
end;
|
|
|
|
|
|
-procedure TFpcBinaryDatapacketReader.EndStoreRecord(
|
|
|
- const AChangeLog: TChangeLogEntryArr);
|
|
|
+procedure TFpcBinaryDatapacketReader.EndStoreRecord;
|
|
|
begin
|
|
|
-// inherited EndStoreRecord(AChangeLog);
|
|
|
+// Do nothing
|
|
|
end;
|
|
|
|
|
|
function TFpcBinaryDatapacketReader.GetCurrentRecord: boolean;
|
|
@@ -3070,18 +3088,17 @@ end;
|
|
|
|
|
|
procedure TFpcBinaryDatapacketReader.GotoElement(const AnElement: pointer);
|
|
|
begin
|
|
|
-// inherited GotoElement(AnElement);
|
|
|
+// Do nothing
|
|
|
end;
|
|
|
|
|
|
-procedure TFpcBinaryDatapacketReader.InitLoadRecords(
|
|
|
- var AChangeLog: TChangeLogEntryArr);
|
|
|
+procedure TFpcBinaryDatapacketReader.InitLoadRecords;
|
|
|
begin
|
|
|
- SetLength(AChangeLog,0);
|
|
|
+// SetLength(AChangeLog,0);
|
|
|
end;
|
|
|
|
|
|
function TFpcBinaryDatapacketReader.GetCurrentElement: pointer;
|
|
|
begin
|
|
|
-// Result:=inherited GetCurrentElement;
|
|
|
+// Do nothing
|
|
|
end;
|
|
|
|
|
|
procedure TFpcBinaryDatapacketReader.RestoreRecord(ADataset: TBufDataset);
|
|
@@ -3090,10 +3107,13 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TFpcBinaryDatapacketReader.StoreRecord(ADataset: TBufDataset;
|
|
|
- RowState: TRowState);
|
|
|
+ ARowState: TRowState; AUpdOrder : integer);
|
|
|
begin
|
|
|
// Ugly because private members of ADataset are used...
|
|
|
Stream.WriteByte($fe);
|
|
|
+ Stream.WriteByte(RowStateToByte(ARowState));
|
|
|
+ if ARowState<>[] then
|
|
|
+ Stream.WriteBuffer(AUpdOrder,sizeof(integer));
|
|
|
Stream.WriteBuffer(ADataset.GetCurrentBuffer^,ADataset.FRecordSize);
|
|
|
end;
|
|
|
|