* Patch from orinaudo@gmail.com:

+ 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 -
This commit is contained in:
michael 2006-10-07 19:25:27 +00:00
parent dfd3b2503e
commit 0c669fbad0

View File

@ -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: harri.kasulke@okay.net E-mail: harri.kasulke@okay.net
} }
@ -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; //FFieldOffsetList calculated once in createtable
for I:=1 to FieldNo-1 do Result:=Integer(FFieldOffsetList.Items[FieldNo-1]);
Result:=Result+MDSGetFieldSize(I);
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 begin
for I:=1 to FieldCount do FillChar(Buffer^,FRecSize,0);
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;
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; MDSSetRecInfo( Buffer,bfCurrent,FCurrRecNo );
PRecInfo(Buffer+FRecInfoOffset)^.BookmarkFlag:=bfCurrent;
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; iSize:=0;
for I:=1 to FieldDefs.Count do for I:=1 to FieldDefs.Count do begin
FRecSize:=FRecSize+MDSGetFieldSize(I); FFieldOffsetList.Add(Pointer(iSize));
FRecInfoOffset:=FRecSize; iSize:=iSize+MDSGetFieldSize(I);
FRecSize:=FRecSize+FRecInfoSize; 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]; F:=Dataset.Fields[I];
TFieldDef.Create(FieldDefs,F.FieldName,F.DataType,F.Size,F.Required,F.FieldNo); 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