Преглед на файлове

* Patch from [email protected]:
+ 4 methods added to encapsulate RecInfo access (that was causing alignement troubles in several places under wince)
+ const added to define size (now 200) when string Field with zero size are copied from other datasets
+ cache added for fields offset instead of recalculating sum(fields size) everytime

git-svn-id: trunk@4822 -

michael преди 19 години
родител
ревизия
0c669fbad0
променени са 1 файла, в които са добавени 83 реда и са изтрити 50 реда
  1. 83 50
      fcl/db/memds/memds.pp

+ 83 - 50
fcl/db/memds/memds.pp

@@ -1,6 +1,6 @@
 {
 {
     This file is part of the Free Component Library (FCL)
     This file is part of the Free Component Library (FCL)
-    Copyright (c) 1999-2000 by the Free Pascal development team
+    Copyright (c) 1999-2006 by the Free Pascal development team
 
 
     See the file COPYING.FPC, included in this distribution,
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
     for details about the copyright.
@@ -10,13 +10,14 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 
  **********************************************************************}
  **********************************************************************}
+{$IFDEF FPC}
 {$mode objfpc}
 {$mode objfpc}
+{$ENDIF FPC}
 {$H+}
 {$H+}
 {
 {
   TMemDataset : In-memory dataset.
   TMemDataset : In-memory dataset.
   - Has possibility to copy Structure/Data from other dataset.
   - Has possibility to copy Structure/Data from other dataset.
   - Can load/save to/from stream.
   - Can load/save to/from stream.
-
   Ideas taken from THKMemTab Component by Harri Kasulke - Hamburg/Germany
   Ideas taken from THKMemTab Component by Harri Kasulke - Hamburg/Germany
   E-mail: [email protected]
   E-mail: [email protected]
 }
 }
@@ -30,6 +31,9 @@ uses
   SysUtils, Classes, DB;
   SysUtils, Classes, DB;
 
 
 Const
 Const
+  //Default size used when string size is 0
+  MEMDS_STRING_MAXSIZE = 200;
+
   // Stream Markers.
   // Stream Markers.
   MarkerSize  = SizeOf(Integer);
   MarkerSize  = SizeOf(Integer);
 
 
@@ -67,6 +71,7 @@ type
     FCurrRecNo: integer;
     FCurrRecNo: integer;
     FIsOpen: boolean;
     FIsOpen: boolean;
     FFilterBuffer: PChar;
     FFilterBuffer: PChar;
+    FFieldOffsetList : TList;
   protected
   protected
     // Mandatory
     // Mandatory
     function  AllocRecordBuffer: PChar; override;
     function  AllocRecordBuffer: PChar; override;
@@ -118,7 +123,14 @@ type
     procedure MDSWriteRecord(Buffer:PChar;ARecNo:Integer);
     procedure MDSWriteRecord(Buffer:PChar;ARecNo:Integer);
     procedure MDSAppendRecord(Buffer:PChar);
     procedure MDSAppendRecord(Buffer:PChar);
     function  MDSFilterRecord(Buffer: PChar): Boolean;
     function  MDSFilterRecord(Buffer: PChar): Boolean;
-
+    function  MDSGetRecInfo(Buffer: PChar): TMTRecInfo;
+    procedure MDSSetRecInfo(Buffer: PChar;
+                            Flag: TBookmarkFlag); 
+    procedure MDSSetRecInfo(Buffer: PChar;
+                            Flag: TBookmarkFlag;
+                            ABookmark: Longint); 
+    procedure MDSSetRecInfo(Buffer: PChar;
+                            ABookmark: Longint); 
   public
   public
     constructor Create(AOwner:tComponent); override;
     constructor Create(AOwner:tComponent); override;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -226,6 +238,7 @@ constructor TMemDataset.Create(AOwner:tComponent);
 begin
 begin
   inherited create(aOwner);
   inherited create(aOwner);
   FStream:=TMemoryStream.Create;
   FStream:=TMemoryStream.Create;
+  FFieldOffsetList := TList.Create;
   FRecInfoSize:=SizeOf(TMTRecInfo);
   FRecInfoSize:=SizeOf(TMTRecInfo);
   FRecCount:=0;
   FRecCount:=0;
   FRecSize:=0;
   FRecSize:=0;
@@ -238,6 +251,7 @@ end;
 Destructor TMemDataset.Destroy;
 Destructor TMemDataset.Destroy;
 begin
 begin
   FStream.Free;
   FStream.Free;
+  FFieldOffsetList.Free;
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -247,14 +261,9 @@ begin
 end;
 end;
 
 
 function TMemDataset.MDSGetFieldOffset(FieldNo: integer): integer;
 function TMemDataset.MDSGetFieldOffset(FieldNo: integer): integer;
-
-var
-  I : integer;
-
 begin
 begin
-  Result:=0;
-  for I:=1 to FieldNo-1 do
-    Result:=Result+MDSGetFieldSize(I);
+  //FFieldOffsetList calculated once in createtable
+  Result:=Integer(FFieldOffsetList.Items[FieldNo-1]);
 end;
 end;
 
 
 Procedure TMemDataset.RaiseError(Fmt : String; Args : Array of const);
 Procedure TMemDataset.RaiseError(Fmt : String; Args : Array of const);
@@ -298,7 +307,7 @@ begin
  else
  else
    Buffer:=nil;
    Buffer:=nil;
  end;
  end;
- Result:=(Buffer<>nil);
+ Result:=Assigned(Buffer);
 end;
 end;
 
 
 procedure TMemDataset.MDSReadRecord(Buffer:PChar;ARecNo:Integer);   //Reads a Rec from Stream in Buffer
 procedure TMemDataset.MDSReadRecord(Buffer:PChar;ARecNo:Integer);   //Reads a Rec from Stream in Buffer
@@ -334,23 +343,8 @@ end;
 
 
 procedure TMemDataset.InternalInitRecord(Buffer: PChar);
 procedure TMemDataset.InternalInitRecord(Buffer: PChar);
 
 
-var
-  I : integer;
-
-begin
- for I:=1 to FieldCount do
-   case FieldDefs.Items[I-1].Datatype of
-     ftString:   pChar(Buffer+MDSGetFieldOffset(I))^:=#0;
-     ftBoolean:  pBoolean(Buffer+MDSGetFieldOffset(I))^:=False;
-     ftFloat:    pFloat(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftLargeint: PInt64(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftSmallInt: pSmallInt(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftInteger:  pInteger(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftCurrency: pFloat(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftDate:     pFloat(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftTime:     pFloat(Buffer+MDSGetFieldOffset(I))^:=0;
-     ftDateTime: pFloat(Buffer+MDSGetFieldOffset(I))^:=0;
-   end;
+begin
+ FillChar(Buffer^,FRecSize,0);
 end;
 end;
 
 
 procedure TMemDataset.InternalDelete;
 procedure TMemDataset.InternalDelete;
@@ -626,7 +620,6 @@ begin
 end;
 end;
 
 
 function TMemDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
 function TMemDataset.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
-
 var
 var
   Accepted: Boolean;
   Accepted: Boolean;
 
 
@@ -657,8 +650,8 @@ begin
     if result=grOK then
     if result=grOK then
       begin
       begin
       MDSReadRecord(Buffer, FCurrRecNo);
       MDSReadRecord(Buffer, FCurrRecNo);
-      PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=FCurrRecNo;
-      PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag:=bfCurrent;
+      MDSSetRecInfo( Buffer,bfCurrent,FCurrRecNo );
+
       if (Filtered) then
       if (Filtered) then
         Accepted:=MDSFilterRecord(Buffer) //Filtering
         Accepted:=MDSFilterRecord(Buffer) //Filtering
       else
       else
@@ -721,36 +714,34 @@ var
   ReqBookmark: integer;
   ReqBookmark: integer;
 
 
 begin
 begin
-  ReqBookmark:=PRecInfo(Buffer+FRecInfoOffset)^.Bookmark;
+  ReqBookmark:=MDSGetRecInfo(Buffer).Bookmark;
   InternalGotoBookmark (@ReqBookmark);
   InternalGotoBookmark (@ReqBookmark);
 end;
 end;
 
 
 function TMemDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
 function TMemDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
-
 begin
 begin
-  Result:=PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag;
+ Result:=MDSGetRecInfo(Buffer).BookmarkFlag;
 end;
 end;
 
 
 procedure TMemDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
 procedure TMemDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
-
 begin
 begin
-  PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag := Value;
+  MDSSetRecInfo(Buffer,Value);
 end;
 end;
 
 
 procedure TMemDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
 procedure TMemDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
 
 
 begin
 begin
   if Data<>nil then
   if Data<>nil then
-    PInteger(Data)^:=PRecInfo(Buffer+FRecInfoOffset)^.Bookmark;
+    PInteger(Data)^:=MDSGetRecInfo(Buffer).Bookmark;
 end;
 end;
 
 
 procedure TMemDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
 procedure TMemDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
 
 
 begin
 begin
   if Data<>nil then
   if Data<>nil then
-    PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=PInteger(Data)^
+    MDSSetRecInfo(Buffer, PInteger(Data)^)
   else
   else
-    PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=0;
+    MDSSetRecInfo( Buffer, 0);
 end;
 end;
 
 
 function TMemDataset.MDSFilterRecord(Buffer: PChar): Boolean;
 function TMemDataset.MDSFilterRecord(Buffer: PChar): Boolean;
@@ -768,6 +759,44 @@ begin
   RestoreState(SaveState);
   RestoreState(SaveState);
 end;
 end;
 
 
+function  TMemDataset.MDSGetRecInfo(Buffer: PChar): TMTRecInfo;
+begin
+  Move(PRecInfo(Buffer+FRecInfoOffset)^,Result,FRecInfoSize);
+end;
+
+procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
+                                    Flag: TBookmarkFlag);
+var ARecInfo: TMTRecInfo;
+begin
+  //Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).BookmarkFlag := Flag;
+  ARecInfo:=MDSGetRecInfo(Buffer);
+  ARecInfo.BookmarkFlag:=Flag;
+  Move(ARecInfo,PRecInfo(Buffer+FRecInfoOffset)^,FRecInfoSize);
+end;
+
+procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
+                                    Flag: TBookmarkFlag;
+                                    ABookmark: Longint);
+var ARecInfo: TMTRecInfo;
+begin
+  //Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).Bookmark := ABookmark;
+  //Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).BookmarkFlag := Flag;
+  ARecInfo:=MDSGetRecInfo(Buffer);
+  ARecInfo.Bookmark:=ABookmark;
+  ARecInfo.BookmarkFlag:=Flag;
+  Move(ARecInfo,PRecInfo(Buffer+FRecInfoOffset)^,FRecInfoSize);
+end;
+
+procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
+                                    ABookmark: Longint);
+var ARecInfo: TMTRecInfo;
+begin
+  //Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).BookmarkFlag := ABookmark;
+  ARecInfo:=MDSGetRecInfo(Buffer);
+  ARecInfo.Bookmark:=ABookmark;
+  Move(ARecInfo,PRecInfo(Buffer+FRecInfoOffset)^,FRecInfoSize);
+end;
+
 Function TMemDataset.DataSize : Integer;
 Function TMemDataset.DataSize : Integer;
 
 
 begin
 begin
@@ -796,20 +825,20 @@ begin
 end;
 end;
 
 
 procedure TMemDataset.CreateTable;
 procedure TMemDataset.CreateTable;
-
 var
 var
-  I : integer;
-
+  i, iSize : Longint;
 begin
 begin
   FStream.Clear;
   FStream.Clear;
   FRecCount:=0;
   FRecCount:=0;
   FCurrRecNo:=-1;
   FCurrRecNo:=-1;
   FIsOpen:=False;
   FIsOpen:=False;
-  FRecSize:=0;
-  for I:=1 to FieldDefs.Count do
-    FRecSize:=FRecSize+MDSGetFieldSize(I);
-  FRecInfoOffset:=FRecSize;
-  FRecSize:=FRecSize+FRecInfoSize;
+  iSize:=0;
+  for I:=1 to FieldDefs.Count do begin
+    FFieldOffsetList.Add(Pointer(iSize));
+    iSize:=iSize+MDSGetFieldSize(I);
+  end;
+  FRecInfoOffset:=iSize;
+  FRecSize:=iSize+FRecInfoSize;
   FRecBufferSize:=FRecSize;
   FRecBufferSize:=FRecSize;
 end;
 end;
 
 
@@ -857,7 +886,7 @@ end;
 Procedure TMemDataset.CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
 Procedure TMemDataset.CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
 
 
 Var
 Var
-  I  : Integer;
+  I, iDataSize : Integer;
   F,F1,F2 : TField;
   F,F1,F2 : TField;
   L1,L2  : TList;
   L1,L2  : TList;
   N : String;
   N : String;
@@ -867,8 +896,12 @@ begin
   // NOT from fielddefs. The data may not be available in buffers !!
   // NOT from fielddefs. The data may not be available in buffers !!
   For I:=0 to Dataset.FieldCount-1 do
   For I:=0 to Dataset.FieldCount-1 do
     begin
     begin
-    F:=Dataset.Fields[I];
-    TFieldDef.Create(FieldDefs,F.FieldName,F.DataType,F.Size,F.Required,F.FieldNo);
+     F:=Dataset.Fields[I];
+     if (F.DataType=ftString) and (F.Size=0)
+     then iDataSize:=MEMDS_STRING_MAXSIZE
+     else iDataSize:=F.Size;
+
+     TFieldDef.Create(FieldDefs,F.FieldName,F.DataType,iDataSize,F.Required,F.FieldNo);
     end;
     end;
   CreateTable;
   CreateTable;
   If CopyData then
   If CopyData then