Browse Source

* Integrated some improvements by Martin Schreiber

git-svn-id: trunk@7939 -
michael 18 years ago
parent
commit
d9b1dbbec9
1 changed files with 149 additions and 141 deletions
  1. 149 141
      packages/fcl-db/src/memds/memds.pp

+ 149 - 141
packages/fcl-db/src/memds/memds.pp

@@ -1,6 +1,7 @@
 {
 {
     This file is part of the Free Component Library (FCL)
     This file is part of the Free Component Library (FCL)
-    Copyright (c) 1999-2006 by the Free Pascal development team
+    Copyright (c) 1999-2007 by the Free Pascal development team
+    Some modifications (c) 2007 by Martin Schreiber
 
 
     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,9 +11,7 @@
     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.
@@ -22,18 +21,14 @@
   E-mail: [email protected]
   E-mail: [email protected]
 }
 }
 
 
-
 unit memds;
 unit memds;
 
 
 interface
 interface
 
 
 uses
 uses
-  SysUtils, Classes, DB;
-
-Const
-  //Default size used when string size is 0
-  MEMDS_STRING_MAXSIZE = 200;
+ sysutils, classes, db, types;
 
 
+const
   // Stream Markers.
   // Stream Markers.
   MarkerSize  = SizeOf(Integer);
   MarkerSize  = SizeOf(Integer);
 
 
@@ -50,28 +45,30 @@ type
     BookmarkFlag: TBookmarkFlag;
     BookmarkFlag: TBookmarkFlag;
   end;
   end;
 
 
-  PInteger  = ^Integer;
-  PSmallInt = ^SmallInt;
-  PInt64    = ^Int64;
-  PFloat    = ^Double;
-  PBoolean  = ^Boolean;
-
-
   TMemDataset=class(TDataSet)
   TMemDataset=class(TDataSet)
   private
   private
     FOpenStream : TStream;
     FOpenStream : TStream;
     FFileName : String;
     FFileName : String;
-    FModified : Boolean;
+    FFileModified : Boolean;
     FStream: TMemoryStream;
     FStream: TMemoryStream;
     FRecInfoOffset: integer;
     FRecInfoOffset: integer;
-    FRecInfoSize: integer;
     FRecCount: integer;
     FRecCount: integer;
     FRecSize: integer;
     FRecSize: integer;
     FRecBufferSize: integer;
     FRecBufferSize: integer;
     FCurrRecNo: integer;
     FCurrRecNo: integer;
     FIsOpen: boolean;
     FIsOpen: boolean;
     FFilterBuffer: PChar;
     FFilterBuffer: PChar;
-    FFieldOffsetList : TList;
+    ffieldoffsets: PInteger;
+    ffieldsizes: PInteger;
+    procedure calcrecordlayout;
+    function  MDSGetRecordOffset(ARecNo: integer): longint;
+    function  MDSGetFieldOffset(FieldNo: integer): integer;
+    function  MDSGetBufferSize(FieldNo: integer): integer;
+    function  MDSGetActiveBuffer(var Buffer: PChar): Boolean;
+    procedure MDSReadRecord(Buffer:PChar;ARecNo:Integer);
+    procedure MDSWriteRecord(Buffer:PChar;ARecNo:Integer);
+    procedure MDSAppendRecord(Buffer:PChar);
+    function  MDSFilterRecord(Buffer: PChar): Boolean;
   protected
   protected
     // Mandatory
     // Mandatory
     function  AllocRecordBuffer: PChar; override;
     function  AllocRecordBuffer: PChar; override;
@@ -114,23 +111,7 @@ type
     // If SaveData=False, a size 0 block should be written.
     // If SaveData=False, a size 0 block should be written.
     Procedure SaveDataToStream(F : TStream; SaveData : Boolean); virtual;
     Procedure SaveDataToStream(F : TStream; SaveData : Boolean); virtual;
 
 
-  private
-    function  MDSGetRecordOffset(ARecNo: integer): longint;
-    function  MDSGetFieldOffset(FieldNo: integer): integer;
-    function  MDSGetFieldSize(FieldNo: integer): integer;
-    function  MDSGetActiveBuffer(var Buffer: PChar): Boolean;
-    procedure MDSReadRecord(Buffer:PChar;ARecNo:Integer);
-    procedure MDSWriteRecord(Buffer:PChar;ARecNo:Integer);
-    procedure MDSAppendRecord(Buffer:PChar);
-    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;
@@ -149,7 +130,7 @@ type
     Procedure CopyFromDataset(DataSet : TDataSet);
     Procedure CopyFromDataset(DataSet : TDataSet);
     Procedure CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
     Procedure CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
 
 
-    Property Modified : Boolean Read FModified;
+    Property FileModified : Boolean Read FFileModified;
 
 
   published
   published
     Property FileName : String Read FFileName Write FFileName;
     Property FileName : String Read FFileName Write FFileName;
@@ -188,6 +169,33 @@ ResourceString
   SErrInvalidMarkerAtPos    = 'Wrong data stream marker at position %d. Got %d, expected %d';
   SErrInvalidMarkerAtPos    = 'Wrong data stream marker at position %d. Got %d, expected %d';
   SErrNoFileName            = 'Filename must not be empty.';
   SErrNoFileName            = 'Filename must not be empty.';
 
 
+Const
+  SizeRecInfo = SizeOf(TMTRecInfo);
+
+procedure unsetfieldisnull(nullmask: pbyte; const x: integer);
+
+begin
+ inc(nullmask,(x shr 3));
+ nullmask^:= nullmask^ or (1 shl (x and 7));
+end;
+
+
+procedure setfieldisnull(nullmask: pbyte; const x: integer);
+
+begin
+ inc(nullmask,(x shr 3));
+ nullmask^:= nullmask^ and Not (1 shl (x and 7));
+end;
+
+
+function getfieldisnull(nullmask: pbyte; const x: integer): boolean;
+
+begin
+ inc(nullmask,(x shr 3));
+ result:= nullmask^ and (1 shl (x and 7)) = 0;
+end;
+
+
 { ---------------------------------------------------------------------
 { ---------------------------------------------------------------------
     Stream functions
     Stream functions
   ---------------------------------------------------------------------}
   ---------------------------------------------------------------------}
@@ -238,8 +246,6 @@ 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);
   FRecCount:=0;
   FRecCount:=0;
   FRecSize:=0;
   FRecSize:=0;
   FRecBufferSize:=0;
   FRecBufferSize:=0;
@@ -251,7 +257,6 @@ end;
 Destructor TMemDataset.Destroy;
 Destructor TMemDataset.Destroy;
 begin
 begin
   FStream.Free;
   FStream.Free;
-  FFieldOffsetList.Free;
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
@@ -262,8 +267,7 @@ end;
 
 
 function TMemDataset.MDSGetFieldOffset(FieldNo: integer): integer;
 function TMemDataset.MDSGetFieldOffset(FieldNo: integer): integer;
 begin
 begin
-  //FFieldOffsetList calculated once in createtable
-  Result:=Integer(FFieldOffsetList.Items[FieldNo-1]);
+ result:= ffieldoffsets[fieldno-1];
 end;
 end;
 
 
 Procedure TMemDataset.RaiseError(Fmt : String; Args : Array of const);
 Procedure TMemDataset.RaiseError(Fmt : String; Args : Array of const);
@@ -272,21 +276,22 @@ begin
   Raise MDSError.CreateFmt(Fmt,Args);
   Raise MDSError.CreateFmt(Fmt,Args);
 end;
 end;
 
 
-function TMemDataset.MDSGetFieldSize(FieldNo: integer): integer;
-
-begin
-  case FieldDefs.Items[FieldNo-1].Datatype of
-   ftString:   result:=FieldDefs.Items[FieldNo-1].Size+1;
-   ftBoolean:  result:=SizeOf(Wordbool);
-   ftFloat:    result:=SizeOf(Double);
-   ftLargeInt: result:=SizeOf(int64);
-   ftSmallInt: result:=SizeOf(SmallInt);
-   ftInteger:  result:=SizeOf(Integer);
-   ftDate:     result:=SizeOf(TDateTime);
-   ftTime:     result:=SizeOf(TDateTime);
-   ftDateTime: result:=SizeOf(TDateTime);
+function TMemDataset.MDSGetBufferSize(FieldNo: integer): integer;
+var
+ dt1: tfieldtype;
+begin
+ dt1:= FieldDefs.Items[FieldNo-1].Datatype;
+ case dt1 of
+  ftString:   result:=FieldDefs.Items[FieldNo-1].Size+1;
+  ftBoolean:  result:=SizeOf(Wordbool);
+  ftFloat:    result:=SizeOf(Double);
+  ftLargeInt: result:=SizeOf(int64);
+  ftSmallInt: result:=SizeOf(SmallInt);
+  ftInteger:  result:=SizeOf(Integer);
+  ftDate:     result:=SizeOf(TDateTime);
+  ftTime:     result:=SizeOf(TDateTime);
  else
  else
-   RaiseError(SErrFieldTypeNotSupported,[FieldDefs.Items[FieldNo-1].Name]);
+  RaiseError(SErrFieldTypeNotSupported,[FieldDefs.Items[FieldNo-1].Name]);
  end;
  end;
 end;
 end;
 
 
@@ -299,7 +304,6 @@ begin
        Buffer:=nil
        Buffer:=nil
      else
      else
        Buffer:=ActiveBuffer;
        Buffer:=ActiveBuffer;
-
   dsEdit,
   dsEdit,
   dsInsert:
   dsInsert:
      Buffer:=ActiveBuffer;
      Buffer:=ActiveBuffer;
@@ -308,7 +312,7 @@ begin
  else
  else
    Buffer:=nil;
    Buffer:=nil;
  end;
  end;
- Result:=Assigned(Buffer);
+ Result:=(Buffer<>nil);
 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
@@ -321,14 +325,14 @@ procedure TMemDataset.MDSWriteRecord(Buffer:PChar;ARecNo:Integer);  //Writes a R
 begin
 begin
   FStream.Position:=MDSGetRecordOffset(ARecNo);
   FStream.Position:=MDSGetRecordOffset(ARecNo);
   FStream.WriteBuffer(Buffer^, FRecSize);
   FStream.WriteBuffer(Buffer^, FRecSize);
-  FModified:=True;
+  FFileModified:=True;
 end;
 end;
 
 
 procedure TMemDataset.MDSAppendRecord(Buffer:PChar);   //Appends a Rec (from Buffer) to Stream
 procedure TMemDataset.MDSAppendRecord(Buffer:PChar);   //Appends a Rec (from Buffer) to Stream
 begin
 begin
   FStream.Position:=MDSGetRecordOffset(FRecCount);
   FStream.Position:=MDSGetRecordOffset(FRecCount);
   FStream.WriteBuffer(Buffer^, FRecSize);
   FStream.WriteBuffer(Buffer^, FRecSize);
-  FModified:=True;
+  FFileModified:=True;
 end;
 end;
 
 
 //Abstract Overrides
 //Abstract Overrides
@@ -344,8 +348,11 @@ end;
 
 
 procedure TMemDataset.InternalInitRecord(Buffer: PChar);
 procedure TMemDataset.InternalInitRecord(Buffer: PChar);
 
 
+var
+  I : integer;
+
 begin
 begin
- FillChar(Buffer^,FRecSize,0);
+ fillchar(buffer^,frecsize,0);
 end;
 end;
 
 
 procedure TMemDataset.InternalDelete;
 procedure TMemDataset.InternalDelete;
@@ -387,7 +394,7 @@ begin
   Finally
   Finally
     TS.Free;
     TS.Free;
   end;
   end;
-  FModified:=True;
+  FFileModified:=True;
 end;
 end;
 
 
 procedure TMemDataset.InternalInitFieldDefs;
 procedure TMemDataset.InternalInitFieldDefs;
@@ -477,7 +484,7 @@ begin
   CheckMarker(F,smData);
   CheckMarker(F,smData);
   Size:=ReadInteger(F);
   Size:=ReadInteger(F);
   FStream.Clear;
   FStream.Clear;
-  if Size>0 then FStream.CopyFrom(F,Size);
+  FStream.CopyFrom(F,Size);
   FRecCount:=Size div FRecSize;
   FRecCount:=Size div FRecSize;
   FCurrRecNo:=-1;
   FCurrRecNo:=-1;
 end;
 end;
@@ -489,7 +496,7 @@ begin
   ReadFieldDefsFromStream(F);
   ReadFieldDefsFromStream(F);
   LoadDataFromStream(F);
   LoadDataFromStream(F);
   CheckMarker(F,smEOF);
   CheckMarker(F,smEOF);
-  FModified:=False;
+  FFileModified:=False;
 end;
 end;
 
 
 Procedure TMemDataSet.LoadFromFile(AFileName : String);
 Procedure TMemDataSet.LoadFromFile(AFileName : String);
@@ -582,7 +589,7 @@ begin
     WriteInteger(F,FStream.Size);
     WriteInteger(F,FStream.Size);
     FStream.Position:=0;
     FStream.Position:=0;
     F.CopyFrom(FStream,FStream.Size);
     F.CopyFrom(FStream,FStream.Size);
-    FModified:=False;
+    FFileModified:=False;
     end
     end
   else
   else
     begin
     begin
@@ -594,13 +601,17 @@ end;
 procedure TMemDataset.InternalClose;
 procedure TMemDataset.InternalClose;
 
 
 begin
 begin
-  if (FModified) and (FFileName<>'') then
-    SaveToFile(FFileName,True);
-  FIsOpen:=False;
-  FModified:=False;
-  BindFields(False);
-  if DefaultFields then
-    DestroyFields;
+ if (FFileModified) and (FFileName<>'') then begin
+  SaveToFile(FFileName,True);
+ end;
+ FIsOpen:=False;
+ FFileModified:=False;
+ BindFields(False);
+ if DefaultFields then begin
+  DestroyFields;
+ end;
+ FreeAndNil(FFieldOffsets);
+ FreeAndNil(FFieldSizes);
 end;
 end;
 
 
 procedure TMemDataset.InternalPost;
 procedure TMemDataset.InternalPost;
@@ -621,6 +632,7 @@ 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;
 
 
@@ -651,8 +663,8 @@ begin
     if result=grOK then
     if result=grOK then
       begin
       begin
       MDSReadRecord(Buffer, FCurrRecNo);
       MDSReadRecord(Buffer, FCurrRecNo);
-      MDSSetRecInfo( Buffer,bfCurrent,FCurrRecNo );
-
+      PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=FCurrRecNo;
+      PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag:=bfCurrent;
       if (Filtered) then
       if (Filtered) then
         Accepted:=MDSFilterRecord(Buffer) //Filtering
         Accepted:=MDSFilterRecord(Buffer) //Filtering
       else
       else
@@ -664,36 +676,46 @@ begin
 end;
 end;
 
 
 function TMemDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
 function TMemDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
-
 var
 var
-  SrcBuffer: PChar;
-
+ SrcBuffer: PChar;
+ I: integer;
 begin
 begin
- result:=False;
- if not MDSGetActiveBuffer(SrcBuffer) then
-   Exit;
- if (Field.FieldNo>0) and (Assigned(Buffer)) and (Assigned(SrcBuffer)) then
+ I:= Field.FieldNo - 1;
+ result:= (I >= 0) and MDSGetActiveBuffer(SrcBuffer) and 
+          not getfieldisnull(pointer(srcbuffer),I);
+ if result and (buffer <> nil) then 
    begin
    begin
-   Move((SrcBuffer+MDSGetFieldOffset(Field.FieldNo))^, Buffer^, MDSGetFieldSize(Field.FieldNo));
-   result:=True;
+   Move((SrcBuffer+ffieldoffsets[I])^, Buffer^,FFieldSizes[I]);
    end;
    end;
 end;
 end;
 
 
 procedure TMemDataset.SetFieldData(Field: TField; Buffer: Pointer);
 procedure TMemDataset.SetFieldData(Field: TField; Buffer: Pointer);
-
 var
 var
-  DestBuffer: PChar;
+ DestBuffer: PChar;
+ I,J: integer;
 
 
 begin
 begin
- MDSGetActiveBuffer(DestBuffer);
- if (Field.FieldNo>0) and (Assigned(Buffer)) and (Assigned(DestBuffer)) then
-   Move(Buffer^,(DestBuffer+MDSGetFieldOffset(Field.FieldNo))^, MDSGetFieldSize(Field.FieldNo));
+ I:= Field.FieldNo - 1;
+ if (I >= 0) and  MDSGetActiveBuffer(DestBuffer) then 
+   begin
+   if buffer = nil then 
+     setfieldisnull(pointer(destbuffer),I)
+   else 
+     begin 
+     unsetfieldisnull(pointer(destbuffer),I);
+     J:=FFieldSizes[I];
+     if Field.DataType=ftString then
+       Dec(J); // Do not move terminating 0, which is in the size.
+     Move(Buffer^,(DestBuffer+FFieldOffsets[I])^,J);
+     dataevent(defieldchange,ptrint(field));
+     end;
+   end;
 end;
 end;
 
 
 function TMemDataset.GetRecordSize: Word;
 function TMemDataset.GetRecordSize: Word;
 
 
 begin
 begin
-  Result:=FRecSize;
+ Result:= FRecSize;
 end;
 end;
 
 
 procedure TMemDataset.InternalGotoBookmark(ABookmark: Pointer);
 procedure TMemDataset.InternalGotoBookmark(ABookmark: Pointer);
@@ -715,34 +737,36 @@ var
   ReqBookmark: integer;
   ReqBookmark: integer;
 
 
 begin
 begin
-  ReqBookmark:=MDSGetRecInfo(Buffer).Bookmark;
+  ReqBookmark:=PRecInfo(Buffer+FRecInfoOffset)^.Bookmark;
   InternalGotoBookmark (@ReqBookmark);
   InternalGotoBookmark (@ReqBookmark);
 end;
 end;
 
 
 function TMemDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
 function TMemDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
+
 begin
 begin
- Result:=MDSGetRecInfo(Buffer).BookmarkFlag;
+  Result:=PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag;
 end;
 end;
 
 
 procedure TMemDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
 procedure TMemDataset.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
+
 begin
 begin
-  MDSSetRecInfo(Buffer,Value);
+  PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag := 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)^:=MDSGetRecInfo(Buffer).Bookmark;
+    PInteger(Data)^:=PRecInfo(Buffer+FRecInfoOffset)^.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
-    MDSSetRecInfo(Buffer, PInteger(Data)^)
+    PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=PInteger(Data)^
   else
   else
-    MDSSetRecInfo( Buffer, 0);
+    PRecInfo(Buffer+FRecInfoOffset)^.Bookmark:=0;
 end;
 end;
 
 
 function TMemDataset.MDSFilterRecord(Buffer: PChar): Boolean;
 function TMemDataset.MDSFilterRecord(Buffer: PChar): Boolean;
@@ -755,34 +779,12 @@ begin
   if not Assigned(OnFilterRecord) then
   if not Assigned(OnFilterRecord) then
     Exit;
     Exit;
   SaveState:=SetTempState(dsFilter);
   SaveState:=SetTempState(dsFilter);
-  FFilterBuffer:=Buffer;
-  OnFilterRecord(Self,Result);
-  RestoreState(SaveState);
-end;
-
-function  TMemDataset.MDSGetRecInfo(Buffer: PChar): TMTRecInfo;
-begin
-  Move(PRecInfo(Buffer+FRecInfoOffset)^,Result,FRecInfoSize);
-end;
-
-procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
-                                    Flag: TBookmarkFlag);
-begin
-  Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).BookmarkFlag := Flag;
-end;
-
-procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
-                                    Flag: TBookmarkFlag;
-                                    ABookmark: Longint);
-begin
-  Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).Bookmark := ABookmark;
-  Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).BookmarkFlag := Flag;
-end;
-
-procedure TMemDataset.MDSSetRecInfo(Buffer: PChar;
-                                    ABookmark: Longint);
-begin
-  Unaligned(PRecInfo(Buffer+FRecInfoOffset)^).Bookmark := ABookmark;
+  Try
+    FFilterBuffer:=Buffer;
+    OnFilterRecord(Self,Result);
+  Finally  
+    RestoreState(SaveState);
+  end;  
 end;
 end;
 
 
 Function TMemDataset.DataSize : Integer;
 Function TMemDataset.DataSize : Integer;
@@ -812,22 +814,32 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TMemDataset.CreateTable;
+procedure tmemdataset.calcrecordlayout;
 var
 var
-  i : Longint;
-  iSize : ptrint;
+  i,count : integer;
+begin
+ Count := fielddefs.count;
+ FFieldOffsets:=getmem(Count*sizeof(integer));
+ FFieldSizes:=getmem(Count*sizeof(integer));
+ FRecSize:= (Count+7) div 8; //null mask
+ for i:= 0 to Count-1 do 
+   begin
+   ffieldoffsets[i] := frecsize;
+   ffieldsizes[i] := MDSGetbufferSize(i+1);
+   FRecSize:= FRecSize+FFieldSizes[i];
+   end;
+end;
+
+procedure TMemDataset.CreateTable;
+
 begin
 begin
   FStream.Clear;
   FStream.Clear;
   FRecCount:=0;
   FRecCount:=0;
   FCurrRecNo:=-1;
   FCurrRecNo:=-1;
   FIsOpen:=False;
   FIsOpen:=False;
-  iSize:=0;
-  for I:=1 to FieldDefs.Count do begin
-    FFieldOffsetList.Add(Pointer(iSize));
-    iSize:=iSize+MDSGetFieldSize(I);
-  end;
-  FRecInfoOffset:=iSize;
-  FRecSize:=iSize+FRecInfoSize;
+  calcrecordlayout;
+  FRecInfoOffset:=FRecSize;
+  FRecSize:=FRecSize+SizeRecInfo;
   FRecBufferSize:=FRecSize;
   FRecBufferSize:=FRecSize;
 end;
 end;
 
 
@@ -854,7 +866,7 @@ Function TMemDataset.GetRecNo: Longint;
 begin
 begin
   UpdateCursorPos;
   UpdateCursorPos;
   if (FCurrRecNo<0) then
   if (FCurrRecNo<0) then
-    Result:=0
+    Result:=1
   else
   else
     Result:=FCurrRecNo+1;
     Result:=FCurrRecNo+1;
 end;
 end;
@@ -875,7 +887,7 @@ end;
 Procedure TMemDataset.CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
 Procedure TMemDataset.CopyFromDataset(DataSet : TDataSet; CopyData : Boolean);
 
 
 Var
 Var
-  I, iDataSize : Integer;
+  I  : Integer;
   F,F1,F2 : TField;
   F,F1,F2 : TField;
   L1,L2  : TList;
   L1,L2  : TList;
   N : String;
   N : String;
@@ -885,12 +897,8 @@ 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];
-     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);
+    F:=Dataset.Fields[I];
+    TFieldDef.Create(FieldDefs,F.FieldName,F.DataType,F.Size,F.Required,F.FieldNo);
     end;
     end;
   CreateTable;
   CreateTable;
   If CopyData then
   If CopyData then