⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbmmembinarystreamformat.pas

📁 内存数据库控件源代码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
                                        ftTime,ftDateTime: Writer.WriteFloat(Fields[i].AsFloat);
                                   else
                                       Writer.WriteString(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.
                    FOverrideActiveRecordBuffer:=FOverrideActiveRecordBuffer^.PrevRecordVersion;
                    NewestVersion:=false;
               end;
               Writer.WriteListEnd;
{$ENDIF}
{$ENDIF}

               // Increment save count.
               inc(FSaveCount);
          end;
          Writer.WriteListEnd;
     end;
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;

     with TkbmProtCustomMemTable(ADataset) do
     begin
          // Now create indexes as defined.
          if InitIndexDef then CreateIndexes;

          FOverrideActiveRecordBuffer:=nil;
     end;

     inherited;
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:boolean;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
   ioptions:TIndexOptions;
   FFields:string;
{$ENDIF}
begin
     if (StreamSize = 0) then exit;
     ld:=sfLoadDef in sfDef;

     with TkbmProtCustomMemTable(ADataset) do
     begin
          // 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
                            Close;
                            FieldDefs.clear;
                            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.
                      FieldDefs.Add(FName,FT,FSize,REQ);

                      // Setup other properties.
                      i:=FieldDefs.IndexOf(FName);
                      with FieldDefs.Items[i].CreateField(ADataset) do
                      begin
                           FieldKind:=FK;
                           DisplayLabel:=DName;
                           EditMask:=EMask;
                           ReadOnly:=RO;
                           DisplayWidth:=DSize;
{$IFDEF LEVEL4}
                           DefaultExpression:=DExpr;
{$ENDIF}
                      end;
                  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;

                  while not(Reader.EndofList) do
                  begin
                       // Clear previous setup if not cleared yet.
                       if not InitIndexDef then
                       begin
                            if ld then
                            begin
                                 DestroyIndexes;
                                 FIndexDefs.Clear;
                            end;
                            InitIndexDef:=true;
                       end;

                       // read index definition.
                       FName := Reader.ReadString;
                       FFields := Reader.ReadString;
                       DName := Reader.ReadString;

                       ioptions:=[];
                       if Reader.ReadBoolean then ioptions:=ioptions+[ixDescending];
                       if Reader.ReadBoolean then ioptions:=ioptions+[ixCaseInSensitive];

{$IFNDEF LEVEL3}
                       if Reader.ReadBoolean then ioptions:=ioptions+[ixNonMaintained];
{$ELSE}
                       Reader.ReadBoolean;     // Skip ixNonMaintained info since not supported for D3/BCB3.
{$ENDIF}
                       if Reader.ReadBoolean then ioptions:=ioptions+[ixUnique];

                       // Add field definition.
                       if ld then
                       begin
{$IFNDEF LEVEL3}
                            with IndexDefs.AddIndexDef do
                            begin
                                 Name:=FName;
                                 Fields:=FFields;
                                 Options:=ioptions;
                                 DisplayName:=DName;
                            end;
{$ELSE}
                            IndexDefs.Add(FName,FFields,ioptions);
{$ENDIF}
                       end;
                  end;
                  Reader.ReadListEnd;
             end;
          finally
             if InitTableDef then Open;
          end;
     end;
     if not ld then InitIndexDef:=false;
end;

procedure TkbmCustomBinaryStreamFormat.LoadData(ADataset:TkbmCustomMemTable);
var
   i:integer;
   nf:integer;
   Accept:boolean;
   bNull:boolean;
   Date:double;
   NewestVersion:boolean;
   pRec:PkbmRecord;
   ApproxRecs:integer;
begin
     if (StreamSize = 0) then exit;
     with TkbmProtCustomMemTable(ADataset),TkbmProtCommon(ADataset.Common) do
     begin
          SetTempState(dsinsert);
          try
             ResetAutoInc;

             // Try to determine approx how many records in stream + add some slack.
             if RecordSize>0 then
             begin
                  ApproxRecs:=StreamSize div FDataRecordSize;
                  ApproxRecs:=ApproxRecs + (ApproxRecs div 50) + RecordCount;
             end
             else
                 ApproxRecs:=0;

             // Read all records.
             FLoadCount:=0;
             FLoadedCompletely:=true;

             if ApproxRecs>0 then FRecords.Capacity:=ApproxRecs; // For speed reason try to preallocate room for all records.
             nf:=Fieldcount;
             Reader.ReadListBegin;
             while not(Reader.EndofList) do
             begin
                  // Show progress.
                  inc(ProgressCnt);
                  ProgressCnt:=ProgressCnt mod 100;
                  if (ProgressCnt=0) then
                     Progress(trunc((WorkStream.Position / StreamSize) * 100),mtpcLoad);

                  if (FLoadLimit>0) and (FLoadCount>=FLoadLimit) then
                  begin
                       FLoadedCompletely:=false;
                       break;
                  end;

                  pRec:=_InternalAllocRecord;
                  FOverrideActiveRecordBuffer:=pRec;

                  NewestVersion:=true;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
 {$IFNDEF BINARY_FILE_200_COMPATIBILITY}                         // New for v. 2.24.

                  // Loop for all versions of record if versioning is used (2.30 and forth).
                  if FileVersion>=230 then Reader.ReadListBegin;
                  while true do
                  begin
                       if FileVersion>=230 then FOverrideActiveRecordBuffer^.UpdateStatus:=TUpdateStatus(Reader.ReadInteger);
 {$ENDIF}
{$ENDIF}

                       // Read fields for current record version.
                       for i:=0 to nf-1 do
                       begin
   //2.50i                          if Fields[i].FieldKind<>fkData then continue;

{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
 {$IFNDEF BINARY_FILE_200_COMPATIBILITY}
  {$IFNDEF BINARY_FILE_230_COMPATIBILITY}                     // New for v. 2.49.
                            // Check if null values saved in binary file.
                            if (FileVersion>=249) then
                               bNull:=Reader.ReadBoolean
                            else
  {$ENDIF}
 {$ENDIF}
{$ENDIF}
                               bNull:=false;

                            // Check if null field.
                            if bNull then
                               Fields[i].Clear
                            else
                            begin
                                 // Not null, load data.
                                 case Fields[i].DataType of
                                      ftBoolean : Fields[i].AsBoolean := Reader.ReadBoolean;

{$IFNDEF LEVEL3}
                                      ftLargeInt: Fields[i].AsFloat := Reader.ReadFloat;
{$ENDIF}

                                      ftSmallInt,
                                      ftInteger,
                                      ftWord : Fields[i].AsInteger := Reader.ReadInteger;

                                      ftAutoInc : with Fields[i] do begin
                                                       AsInteger:=Reader.ReadInteger;
                                                       if FAutoIncMax<AsInteger then
                                                          FAutoIncMax:=AsInteger;
                                                  end;

                                      ftFloat : Fields[i].AsFloat := Reader.ReadFloat;

                                      ftBCD,
                                      ftCurrency : Fields[i].AsCurrency := Reader.ReadFloat;

                                      ftDate,
                                      ftTime,
                                      ftDateTime : begin
                                                      Date:=Reader.ReadFloat;
                                                      if Date=0 then Fields[i].Clear
                                                      else Fields[i].AsFloat:=Date;
                                                   end;
                                 else
                                     Fields[i].AsString := Reader.ReadString;
                                 end;
                            end;

                            if NewestVersion and Assigned(FOnLoadField) then OnLoadField(ADataset,i,Fields[i]);
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
 {$IFNDEF BINARY_FILE_200_COMPATIBILITY}                         // New for v. 2.24.
                       end;

                       // Previous file versions didnt contain versions, so just break loop.
                       if FileVersion<230 then break;

                       // Prepare for reading next version if any. (introduced in v. 2.30)
                       if Reader.EndOfList then break;

                       // Prepare next version.
                       NewestVersion:=false;
                       FOverrideActiveRecordBuffer^.PrevRecordVersion:=_InternalAllocRecord;
                       FOverrideActiveRecordBuffer:=FOverrideActiveRecordBuffer^.PrevRecordVersion;

                  end;
                  if FileVersion>=230 then Reader.ReadListEnd;
 {$ENDIF}
{$ENDIF}

                  Accept:=true;
                  if Assigned(OnLoadRecord) then OnLoadRecord(ADataset,Accept);
                  if Accept then
                  begin
                       pRec^.RecordID:=FRecordID;
                       inc(FRecordID);
                       pRec^.UniqueRecordID:=FUniqueRecordID;
                       inc(FUniqueRecordID);
                       pRec^.Flag:=kbmrfInTable;
                       FRecords.Add(pRec);
                       if pRec^.UpdateStatus=usDeleted then inc(FDeletedCount);
                       inc(FLoadCount);
                  end
                  else
                     _InternalFreeRecord(pRec,true,true);
             end;
             Reader.ReadListEnd;
          finally
             RestoreState(dsBrowse);
          end;
     end;
end;

// -----------------------------------------------------------------------------------
// Registration for Delphi 3 / C++ Builder 3
// -----------------------------------------------------------------------------------

{$ifdef LEVEL3}
procedure Register;
begin
     RegisterComponents('kbmMemTable', [TkbmBinaryStreamFormat]);
end;
{$endif}

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -