📄 kbmmembinarystreamformat.pas
字号:
// Count number of fields actually saved.
j:=0;
for i:=0 to nf-1 do
if SaveFields[i]>=0 then inc(j);
// Start writing header.
Writer.WriteListBegin;
Writer.WriteInteger(j);
for i:=0 to nf-1 do
begin
if SaveFields[i]>=0 then
Writer.WriteInteger(ord(ADataSet.Fields[i].DataType));
end;
Writer.WriteListEnd;
end;
// Write all records
ADataSet.SaveCount := 0;
ADataSet.SavedCompletely:=true;
Writer.WriteListBegin;
// Check if to write according to current index or not.
UsingIndex:=sfSaveUsingIndex in FUsingIndex;
if UsingIndex then
cnt:=ADataSet.CurIndex.References.Count
else
cnt:=TkbmProtCommon(ADataSet.Common).FRecords.Count;
for j:=0 to cnt-1 do
begin
// Check if to save more.
if (ADataSet.SaveLimit>0) and (ADataSet.SaveCount>=ADataSet.SaveLimit) then
begin
ADataSet.SavedCompletely:=false;
break;
end;
// Check if to invoke progress event if any.
if (j mod 100)=0 then ADataSet.Progress(trunc((j/cnt)*100),mtpcSave);
// Setup which record to look at.
if UsingIndex then
ADataSet.OverrideActiveRecordBuffer:=PkbmRecord(ADataSet.CurIndex.References.Items[j])
else
ADataSet.OverrideActiveRecordBuffer:=PkbmRecord(TkbmProtCommon(ADataSet.Common).FRecords.Items[j]);
if (ADataSet.OverrideActiveRecordBuffer=nil) then continue;
// Calculate fields.
ADataSet.__ClearCalcFields({$IFNDEF DOTNET}PChar(ADataSet.OverrideActiveRecordBuffer){$ELSE}ADataSet.OverrideActiveRecordBuffer{$ENDIF});
ADataSet.__GetCalcFields({$IFNDEF DOTNET}PChar(ADataSet.OverrideActiveRecordBuffer){$ELSE}ADataSet.OverrideActiveRecordBuffer{$ENDIF});
// Check filter of record.
Accept:=ADataSet.FilterRecord(ADataSet.OverrideActiveRecordBuffer,false);
if not Accept then continue;
// Check accept of saving this record.
Accept:=true;
if Assigned(ADataSet.OnSaveRecord) then ADataSet.OnSaveRecord(ADataset,Accept);
if not Accept then continue;
// Write current record.
NewestVersion:=true;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
// New for v. 2.24.
{$IFDEF DOTNET}
ARec := TKbmRecord (Marshal.PtrToStructure(ADataSet.OverrideActiveRecordBuffer,TypeOf(TKbmRecord) ));
if (not (sfSaveData in sfData)) and (ARec.UpdateStatus=usUnmodified) then continue;
// New for v. 2.30b
if (not (sfSaveDontFilterDeltas in sfDontFilterDeltas)) and (ARec.UpdateStatus=usDeleted) then
begin
// Make sure record has not been inserted and deleted again.
pRec:=ARec.PrevRecordVersion;
Rec := TKbmRecord (Marshal.PtrToStructure(pRec,TypeOf(TKbmRecord)));
while Rec.PrevRecordVersion<>nil do
begin
pRec:=Rec.PrevRecordVersion;
Rec := TKbmRecord (Marshal.PtrToStructure(pRec,TypeOf(TKbmRecord)));
end;
if Rec.UpdateStatus=usInserted then continue;
end;
{$ELSE}
if (not (sfSaveData in sfData)) and (ADataSet.OverrideActiveRecordBuffer^.UpdateStatus=usUnmodified) then continue;
// New for v. 2.30b
if (not (sfSaveDontFilterDeltas in sfDontFilterDeltas)) and (ADataSet.OverrideActiveRecordBuffer^.UpdateStatus=usDeleted) then
begin
// Make sure record has not been inserted and deleted again.
pRec:=ADataSet.OverrideActiveRecordBuffer^.PrevRecordVersion;
while pRec^.PrevRecordVersion<>nil do pRec:=pRec^.PrevRecordVersion;
if pRec^.UpdateStatus=usInserted then continue;
end;
{$ENDIF}
// Write record versions in a list starting with Updatestatus.
Writer.WriteListBegin;
while ADataSet.OverrideActiveRecordBuffer<>nil do
begin
{$IFDEF DOTNET}
ARec:=TKbmRecord (Marshal.PtrToStructure(ADataSet.OverrideActiveRecordBuffer,TypeOf(TKbmRecord) ));
Writer.WriteInteger(ord(ARec.UpdateStatus));
{$ELSE}
Writer.WriteInteger(ord(ADataSet.OverrideActiveRecordBuffer^.UpdateStatus));
{$ENDIF}
{$ENDIF}
{$ENDIF}
for i:=0 to nf-1 do
begin
if SaveFields[i]>=0 then
begin
if NewestVersion and Assigned(ADataSet.OnSaveField) then ADataSet.OnSaveField(ADataset,i,ADataSet.Fields[i]);
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
{$IFNDEF BINARY_FILE_230_COMPATIBILITY}
Writer.WriteBoolean(ADataSet.Fields[i].IsNull);
if not ADataSet.Fields[i].IsNull then
begin
{$ENDIF}
{$ENDIF}
{$ENDIF}
case ADataSet.Fields[i].DataType of
ftBoolean : Writer.WriteBoolean(ADataSet.Fields[i].AsBoolean);
{$IFNDEF LEVEL3}
ftLargeInt: Writer.WriteFloat(ADataSet.Fields[i].AsFloat);
{$IFDEF DOTNET}
ftWideString: Writer.WriteString(ADataSet.Fields[i].AsString);
{$ELSE}
ftWideString: Writer.WriteString({$IFDEF LEVEL6}UTF8Encode(ADataSet.Fields[i].Value){$ELSE}ADataSet.Fields[i].AsString{$ENDIF});
{$ENDIF}
{$ENDIF}
ftSmallInt,
ftInteger,
ftWord,
ftAutoInc : Writer.WriteInteger(ADataSet.Fields[i].AsInteger);
ftFloat : Writer.WriteFloat(ADataSet.Fields[i].AsFloat);
ftBCD,
ftCurrency : Writer.WriteFloat(ADataSet.Fields[i].AsCurrency);
ftDate,
ftTime,ftDateTime: Writer.WriteFloat(ADataSet.Fields[i].AsFloat);
else
Writer.WriteString(ADataSet.Fields[i].AsString);
end;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
{$IFNDEF BINARY_FILE_230_COMPATIBILITY}
end;
{$ENDIF}
{$ENDIF}
{$ENDIF}
end;
end;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY} // New for v. 2.24.
// Only write newest version (current data).
if not (sfSaveDeltas in sfDeltas) then break;
// Prepare writing next older version of record.
{$IFDEF DOTNET}
ARec:=TKbmRecord(Marshal.PtrToStructure(ADataSet.OverrideActiveRecordBuffer,TypeOf(TKbmRecord)));
ADataSet.OverrideActiveRecordBuffer:=ARec.PrevRecordVersion;
{$ELSE}
ADataSet.OverrideActiveRecordBuffer:=ADataSet.OverrideActiveRecordBuffer^.PrevRecordVersion;
{$ENDIF}
NewestVersion:=false;
end;
Writer.WriteListEnd;
{$ENDIF}
{$ENDIF}
// Increment save count.
ADataSet.SaveCount:=ADataSet.SaveCount + 1;
end;
Writer.WriteListEnd;
end;
procedure TkbmCustomBinaryStreamFormat.BeforeLoad(ADataset:TkbmCustomMemTable);
begin
inherited;
StreamSize:=WorkStream.Size;
ProgressCnt:=0;
Reader:=TReader.Create(WorkStream,FBuffSize);
Reader.ReadSignature;
InitIndexDef:=false;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
if Reader.NextValue = vaList then // A hack since vaList only exists in >= v. 2.xx.
FileVersion := 100
else
FileVersion:=Reader.ReadInteger;
{$ELSE}
FileVersion:=0;
{$ENDIF}
end;
procedure TkbmCustomBinaryStreamFormat.AfterLoad(ADataset:TkbmCustomMemTable);
begin
Reader.Free;
// Now create indexes as defined.
if InitIndexDef then ADataset.CreateIndexes;
ADataset.OverrideActiveRecordBuffer:=nil;
inherited;
end;
procedure TkbmCustomBinaryStreamFormat.DetermineLoadFieldIndex(ADataset:TkbmCustomMemTable; ID:string; FieldCount:integer; OrigIndex:integer; var NewIndex:integer; Situation:TkbmDetermineLoadFieldsSituation);
begin
NewIndex:=OrigIndex;
end;
procedure TkbmCustomBinaryStreamFormat.LoadDef(ADataset:TkbmCustomMemTable);
var
i:integer;
FName,KName,TName,DName,EMask,DExpr:string;
FSize,DSize:integer;
REQ,RO:boolean;
FT:TFieldType;
FK:TFieldKind;
InitTableDef:boolean;
ld,ldidx:boolean;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
ioptions:TIndexOptions;
FFields:string;
{$ENDIF}
aField:TField;
aIndexDef:TIndexDef;
begin
if (StreamSize = 0) then exit;
ld:=sfLoadDef in sfDef;
ldidx:=sfLoadIndexDef in sfIndexDef;
// Read all definitions if any saved.
InitTableDef:=false;
InitIndexDef:=false;
try
Reader.ReadListBegin;
while not(Reader.EndofList) do
begin
// Clear previous setup if not cleared yet.
if not InitTableDef then
begin
if ld then
begin
ADataSet.Close;
ADataSet.FieldDefs.clear;
ADataSet.DeleteTable;
end;
InitTableDef:=true;
end;
// read field definition.
FName := Reader.ReadString;
TName := Reader.ReadString;
FSize := Reader.ReadInteger;
DName := Reader.ReadString;
EMask := Reader.ReadString;
DSize := Reader.ReadInteger;
REQ := Reader.ReadBoolean;
RO := Reader.ReadBoolean;
if FileVersion>=250 then KName:=Reader.ReadString
else KName:=FieldKindNames[0]; // fkData
if FileVersion>=251 then DExpr:=Reader.ReadString
else DExpr:='';
// Find fieldtype from fieldtypename.
for i:=0 to ord(High(FieldTypeNames)) do
if FieldTypeNames[TFieldType(i)]=TName then break;
FT:=TFieldType(i);
if not (FT in kbmSupportedFieldTypes) then
raise EMemTableError.Create(Format(kbmUnknownFieldErr1,[TName]));
// Find fieldkind from fieldkindname.
FK:=fkData;
for i:=0 to ord(High(FieldKindNames)) do
if FieldKindNames[i]=KName then
begin
FK:=TFieldKind(i);
break;
end;
if ld then
begin
// Add field definition.
ADataSet.FieldDefs.Add(FName,FT,FSize,REQ);
// Setup other properties.
i:=ADataSet.FieldDefs.IndexOf(FName);
AField := ADataSet.FieldDefs.Items[i].CreateField(ADataset);
AField.FieldKind:=FK;
AField.DisplayLabel:=DName;
AField.EditMask:=EMask;
AField.ReadOnly:=RO;
AField.DisplayWidth:=DSize;
{$IFDEF LEVEL4}
AField.DefaultExpression:=DExpr;
{$ENDIF}
end;
end;
Reader.ReadListEnd;
// Indexes introduced in file version 2.00
if FileVersion>=200 then
begin
// Read all index definitions if any saved.
Reader.ReadListBegin;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -