home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 October
/
Chip_2001-10_cd1.bin
/
zkuste
/
delphi
/
kompon
/
d45
/
ARDOCI.ZIP
/
VirtualDataSet.pas
< prev
Wrap
Pascal/Delphi Source File
|
2001-06-21
|
25KB
|
893 lines
unit VirtualDataSet;
{
═α±δσΣ≤σ≥± ε≥ TDataSet
▌≥ε wrapper φαΣ TDataSet, Σδ Γ√∩εδφσφΦ Γ±σ⌡ Delphi-specific ⌠≤φΩ÷ΦΘ
}
{
─αφφ√σ Γ ß≤⌠σ≡σ ⌡≡αφ ≥± Γ ΓΦΣσ, ±εΓ∞σ±≥Φ∞ε∞ ± BDE:
ftInteger - ΩαΩ integer(4 ßαΘ≥α)
ftSmallInt - ΩαΩ smallint(2 ßαΘ≥α)
ftFloat - ΩαΩ double (8 ßαΘ≥)
ftCurrency - ΩαΩ double(8 ßαΘ≥)
ftDate - ΩαΩ TDateTimeRec
ftTime - ΩαΩ TDateTimeRec
ftDateTime - ΩαΩ TDateTimeRec
ftWord - ΩαΩ Word(2 ßαΘ≥α)
ftBoolean - ΩαΩ WordBool(2 ßαΘ≥α)
ftBlob,ftMemo - φσ ⌡≡αφ ≥±
ftString - ΩαΩ pchar (Size ßαΘ≥), Γετ∞εµφε ßστ #0 φα ⌡Γε±≥σ
}
interface
uses Db, Classes, DynamicArrays;
type
{$IFDEF VER120} { Borland Delphi 4.0 }
TUpdateAction = (uaFail, uaAbort, uaSkip, uaRetry, uaApplied);
TUpdateRecordEvent = procedure(DataSet: TDataSet; UpdateKind: TUpdateKind; var UpdateAction: TUpdateAction) of object;
{$ENDIF}
TVirtualDataSet = class;
TBookmInfo = record
Bookmark : integer;
BookmarkFlag: TBookmarkFlag;
end;
PBookmInfo=^TBookmInfo;
PInteger=^Integer;
TPutMode = (pmAppend,pmInsert,pmUpdate);
TVirtualFilterRecordEvent = procedure(DataSet: TVirtualDataSet; RecNum : integer;
var Accept: Boolean) of object;
TOnFastCalcFields = procedure(DataSet: TVirtualDataSet; RecNum : integer) of object;
TVirtualDataSet = class(TDataSet)
private
FCalcBuf:pointer;
FFieldsOffset :THArrayInteger;
FFieldsSize :THArrayInteger;
FOpened :boolean;
FRecSize :word;
FFilterRecordEvent :TVirtualFilterRecordEvent;
FOnFastCalcFields :TOnFastCalcFields;
FAfterInternalOpen: TDataSetNotifyEvent;
OldBuffer:pointer;
procedure VReadAll;
protected
FCount :integer;
FCurrent :integer;
FBookm :THArrayInteger;
UniqBookmark :integer;
function GetRecNo : integer; override;
//abstract methods
function VOpen :boolean; virtual; abstract;
function VPrepare :boolean; virtual; abstract;
function VClose :boolean; virtual; abstract;
procedure VGoto(RecordNum :integer); virtual; abstract;
procedure VInitFieldDefs(Opened:boolean); virtual; abstract;
function VGetFieldValue( RecordNum:integer;
FieldID :integer;
Buffer :pointer):boolean; virtual; abstract;
procedure VPutFieldValue( RecordNum:integer;
FieldID :integer;
Buffer :pointer;
mode :TPutMode;
IfNotNull:Boolean);virtual; abstract;
function VPost (RecordNum:integer):TUpdateAction; virtual; abstract;
function VInsert (RecordNum:integer):TUpdateAction; virtual; abstract;
function VDeleteRecord(RecordNum:integer):TUpdateAction; virtual; abstract;
function FetchNextBlock:boolean; virtual; abstract;
function GetRealSize(FieldType:TFieldType;Size:integer):integer;
//overrided methods from TDataSet
procedure InternalOpen; override;
procedure InternalEdit; override;
procedure InternalInitFieldDefs; override;
procedure InternalClose; override;
procedure InternalInsert; override;
function IsCursorOpen:boolean; override;
procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
procedure InternalSetToRecord(Buffer: PChar); override;
procedure InternalGotoBookmark(Bookmark: Pointer); override;
function GetRecordCount:integer; override;
function AllocRecordBuffer:PChar; override;
procedure FreeRecordBuffer(var Buffer: PChar); override;
function GetRecordSize: Word; override;
procedure InternalInitRecord(Buffer: PChar); override;
procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override;
procedure InternalPost; override;
procedure InternalDelete; override;
function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
procedure SetFieldData(Field: TField; Buffer: Pointer); override;
procedure InternalFirst; override;
procedure InternalLast; override;
procedure InternalHandleException; override;
procedure SetFiltered(Value:boolean); override;
procedure SetRecNo(Value : integer); override;
function GetFieldID(FieldName : string) : integer;
function GetFieldCount: integer;
procedure ClearDataSet; virtual;
public
constructor Create(AOwner:TComponent);override;
destructor Destroy; override;
procedure SetFieldValue(RecordNum:integer; FieldID : integer; Value:variant); virtual; abstract;
function GetFieldValue(RecordNum:integer; FieldID : integer):variant; virtual; abstract;
procedure GotoRecNum(RecNum:integer);
function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
procedure OpenAll;
procedure ReOpen;
property RecNo; //for internal use
procedure CopyStructure(DataSet:TDataSet);
function Locate(const KeyFields: string; const KeyValues: Variant;
Options: TLocateOptions): Boolean; override;
function Lookup(const KeyFields: string; const KeyValues: Variant;
const ResultFields: string): Variant;override;
property FieldID[Index:string]:integer read GetFieldID;
property ActiveRecord;
property CurrentRecord;
function CompareBookmarks(Bookmark1,Bookmark2:TBookmark):integer;override;
published
property Active;
property BeforeOpen;
property AfterOpen;
property BeforeClose;
property AfterClose;
property BeforeInsert;
property AfterInsert;
property BeforeEdit;
property AfterEdit;
property BeforePost;
property AfterPost;
property BeforeCancel;
property AfterCancel;
property BeforeDelete;
property AfterDelete;
property BeforeScroll;
property AfterScroll;
property OnFastCalcFields:TOnFastCalcFields read FOnFastCalcFields write FOnFastCalcFields;
property OnDeleteError;
property OnEditError;
property OnNewRecord;
property OnPostError;
property Filtered;
property AfterInternalOpen: TDataSetNotifyEvent read FAfterInternalOpen write FAfterInternalOpen;
property OnVFilterRecord : TVirtualFilterRecordEvent
read FFilterRecordEvent
write FFilterRecordEvent;
end;
implementation
uses SysUtils, DBConsts;
constructor TVirtualDataSet.Create(AOwner:TComponent);
begin
inherited Create(Aowner);
FFieldsOffset:=THArrayInteger.Create;
FFieldsSize:=THArrayInteger.Create;
FBookm:=THArrayInteger.Create;
UniqBookmark:=0;
FCount:=0;
FCurrent:=-1;
FOpened:=False;
FCalcBuf:=nil;
end;
destructor TVirtualDataSet.Destroy;
begin
FFieldsOffset.Free;
FFieldsSize.Free;
FBookm.Free;
inherited Destroy;
end;
procedure TVirtualDataSet.InternalOpen;
var
i :integer;
RealSize :integer;
off :word;
begin
ClearBuffers;
BookmarkSize:=sizeof(TBookmInfo);
FCount:=0;
FCurrent:=-1;
if DefaultFields then begin
VInitFieldDefs(True);
CreateFields;
end;
FOpened:=VOpen;
if not FOpened then exit;
FFieldsOffset.ClearMem;
FFieldsSize.ClearMem;
FBookm.ClearMem;
UniqBookmark:=0;
off:=sizeof(TBookmInfo);
for i:=0 to FieldDefs.Count-1 do begin
FFieldsOffset.AddValue(off);
RealSize:=GetRealSize(FieldDefs[i].DataType,FieldDefs[i].Size);
FFieldsSize.AddValue(RealSize);
off:=off+RealSize+1; //one extra byte for isFieldNull function
end;
FRecSize:=off;
BindFields(True);
OldBuffer:=AllocMem(RecordSize);
if Assigned (AfterInternalOpen) then AfterInternalOpen(self);
end;
function TVirtualDataSet.GetRealSize(FieldType:TFieldType;Size:integer):integer;
begin
case FieldType of
ftFloat : Result:=SizeOf(Double);
ftCurrency : Result:=SizeOf(Currency);
ftInteger : Result:=SizeOf(Integer);
ftSmallInt : Result:=SizeOf(SmallInt);
ftDate : Result:=SizeOf(TDateTimeRec);
ftTime : Result:=SizeOf(TDateTimeRec);
ftWord : Result:=SizeOf(Word);
ftBoolean : Result:=SizeOf(WordBool);
ftDateTime : Result:=SizeOf(TDateTimeRec);
ftString : Result:=Size;
ftBlob,ftMemo : Result:=2*SizeOf(pointer); // BlobSize and pointer to memory where BLOB field stores data
else
Result:=Size;
end;
end;
function TVirtualDataSet.GetFieldID(FieldName : string) : integer;
begin
Result:=FieldDefs.IndexOf(FieldName);
if Result=-1 then raise Exception.Create('Field "'+FieldName+'" not found!');
end;
function TVirtualDataSet.GetFieldCount : integer;
begin
Result:=FieldDefs.Count;
end;
procedure TVirtualDataSet.InternalClose;
begin
if not FOpened then exit;
if DefaultFields then Fields.Clear;
FOpened:=not VClose;
FCount:=0;
FBookm.ClearMem;
FFieldsOffset.ClearMem;
FFieldsSize.ClearMem;
FreeMem(OldBuffer);
OldBuffer:=nil;
end;
procedure TVirtualDataSet.InternalInitFieldDefs;
begin
if Active then exit;
VInitFieldDefs(False);
end;
function TVirtualDataSet.IsCursorOpen:boolean;
begin
Result:=FOpened;
end;
procedure TVirtualDataSet.GetBookmarkData(Buffer: PChar; Data: Pointer);
begin
PInteger(Data)^:=PBookmInfo(Buffer).Bookmark;
end;
procedure TVirtualDataSet.SetBookmarkData(Buffer: PChar; Data: Pointer);
begin
PBookmInfo(Buffer).Bookmark:=PInteger(Data)^;
end;
function TVirtualDataSet.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
begin
Result:=PBookmInfo(Buffer).BookmarkFlag;
end;
procedure TVirtualDataSet.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag);
begin
PBookmInfo(Buffer).BookmarkFlag:=Value;
end;
procedure TVirtualDataSet.InternalSetToRecord(Buffer: PChar);
begin
FCurrent:=FBookm.IndexOf(PBookmInfo(Buffer).Bookmark);
//MoveBy(1);
//PBookmInfo(Buffer).BookmarkFlag := bfCurrent;
{ if PBookmInfo(Buffer).BookmarkFlag=bfBOF then
FCurrent:=FCurrent-1;}
end;
procedure TVirtualDataSet.GotoRecNum(RecNum:integer);
var u:integer;
begin
// b.Bookmark
u:=FBookm[RecNum];
GotoBookmark(@u);
end;
procedure TVirtualDataSet.InternalGotoBookmark(Bookmark: Pointer);
begin
InternalSetToRecord(PChar(bookmark));
end;
function TVirtualDataSet.GetRecordCount:integer;
begin
Result:=FCount;
end;
function TVirtualDataSet.AllocRecordBuffer:PChar;
begin
Result:=AllocMem(FRecSize);
end;
procedure TVirtualDataSet.FreeRecordBuffer(var Buffer: PChar);
begin
FreeMem(Buffer);
end;
function TVirtualDataSet.GetRecordSize: Word;
begin
Result:=FRecSize;
end;
function TVirtualDataSet.GetRecNo : integer;
begin
UpdateCursorPos;
Result:=FCurrent;
end;
procedure TVirtualDataSet.SetRecNo(Value : integer);
begin
if (Value>-1) and (Value<RecordCount) then
begin
FCurrent:=Value;
Resync([]);//Refresh; {roma 13.08.2000}
end;
end;
procedure TVirtualDataSet.InternalInitRecord(Buffer: PChar);
begin
FillChar(Buffer^,RecordSize,#0);
end;
procedure TVirtualDataSet.InternalInsert;
begin
// ∩εΩα φΦ≈σπε
end;
procedure TVirtualDataSet.InternalAddRecord(Buffer: Pointer; Append: Boolean);
var
i : integer;
mode : TPutMode;
r:integer;
begin
r:=FCurrent;
if r=-1 then r:=0;
if Append then r:=RecordCount;
if Append
then mode:=pmAppend
else mode:=pmInsert;
VInsert(r);
for i:=0 to FieldDefs.Count-1 do
VPutFieldValue(r,i,
pointer(cardinal(Buffer) +
cardinal(FFieldsOffset.Value[i])+1),
mode, Boolean(pointer(cardinal(Buffer)+cardinal(FFieldsOffset.Value[i]))^));
// Inc(UniqBookmark); // VInsert automatically call FBookm.Insert
// FBookm.AddValue(UniqBookmark);
if mode=pmAppend then FCurrent:=RecordCount;
Inc(FCount);
end;
procedure TVirtualDataSet.InternalPost;
var
i : integer;
mode : TPutMode;
ua : TUpdateAction;
begin
case State of
dsEdit : begin
ua:=VPost(FCurrent);
if ua<>uaApplied then abort;
if ua=uaAbort then abort;
mode:=pmUpdate;
for i:=0 to FieldDefs.Count-1 do
VPutFieldValue(FCurrent,i,
pointer(cardinal(ActiveBuffer) +
cardinal(FFieldsOffset.Value[i])+1),
mode,
Boolean(pointer(cardinal(ActiveBuffer) +
cardinal(FFieldsOffset.Value[i]))^));
end;
dsInsert : begin
if FCurrent<>-1 then ua:=VPost(FCurrent) else ua:=VPost(0);
if ua=uaAbort then abort;
if ua<>uaApplied then abort;
if PBookmInfo(ActiveBuffer).BookmarkFlag<>bfEOF then
begin
if FCurrent=-1 then
begin
Inc(FCurrent);
InternalAddRecord(ActiveBuffer,False);
Dec(FCurrent);
end else
InternalAddRecord(ActiveBuffer,False)
end else
InternalAddRecord(ActiveBuffer,True);
end;
end;
end;
procedure TVirtualDataSet.InternalDelete;
var ua:TUpdateAction;
begin
ua:=VDeleteRecord(FCurrent);
if ua=uaAbort then abort;
if ua<>uaApplied then raise Exception.Create('Error delete');
InternalInitRecord(ActiveBuffer);
Dec(FCount);
end;
function TVirtualDataSet.GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
var
i :integer;
accept :boolean;
inv :boolean;
// SaveState:TDataSetState;
begin
//inv:=inherited Active;
Result:=grOk;
if GetMode=gmNext then
repeat
FCurrent:=FCurrent+1;
VGoto(FCurrent);
if FCurrent>=RecordCount then break;
accept:=FCurrent<>-1;
if Filtered and Assigned(FFilterRecordEvent) then
FFilterRecordEvent(self,FCurrent,accept);
until accept;
if GetMode=gmPrior then
repeat
FCurrent:=FCurrent-1;
VGoto(FCurrent);
if FCurrent<0 then break; {roma}
accept:=FCurrent<>-1;
if Filtered and Assigned(FFilterRecordEvent) then
FFilterRecordEvent(self,FCurrent,accept);
until accept;
if GetMode=gmCurrent then
begin
VGoto(FCurrent);
accept:=(FCurrent>=0) and (FCurrent<RecordCount);
if Filtered and Assigned(FFilterRecordEvent) and (accept) then
FFilterRecordEvent(self,FCurrent,accept);
if not accept then Result:=grEOF;
end;
if FCurrent>=RecordCount then begin Result:=grEOF; FCurrent:=RecordCount; end;
if FCurrent<0 then begin Result:=grBOF; FCurrent:=-1; end;
if Result=grOk then
// if FCurrent<RecordCount then
begin
if Assigned(OnFastCalcFields) then OnFastCalcFields(self,FCurrent);
for i:=0 to FieldDefs.Count-1 do
begin
inv:=VGetFieldValue(FCurrent,i,
pointer(cardinal(Buffer) + cardinal(FFieldsOffset.Value[i])+1)
);
Boolean(pointer(cardinal(Buffer) + cardinal(FFieldsOffset.Value[i]))^):=inv; // True - σ±δΦ Σαφφ√σ σ±≥ⁿ. False - σ±δΦ ∩εδσ=NULL
end;
FBookm.Get(FCurrent,@(PBookmInfo(Buffer)^.Bookmark));
PBookmInfo(Buffer)^.BookmarkFlag:=bfCurrent;
FCalcBuf:=Buffer;
CalculateFields(Buffer);
FCalcBuf:=nil;
end;
end;
function TVirtualDataSet.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
var
i :integer;
pi:pointer;
begin
// if FDoCalc and Assigned(OnCalculateFields) then
Result:=False;
if IsEmpty and (FCurrent=-1) then exit; // εß τα≥σδⁿφε !!! ╚φα≈σ Γ ∩≤±≥εΘ ≥αßδΦ÷σ ∩εΩατ√Γα■≥± Σαφφ√σ Γ ∩σ≡ΓεΘ ±≥≡εΩσ
i:=GetFieldID(Field.FieldName);
if i>=FFieldsOffset.Count then exit;
if State=dsOldValue
then pi:=OldBuffer
else if Assigned(FCalcBuf)
then pi:=FCalcBuf
else pi:=ActiveBuffer;
pi:=pointer(cardinal(pi)+cardinal(FFieldsOffset.Value[i]));
{ if Assigned(FCalcBuf)
then pi:=pointer(cardinal(FCalcBuf)+ofs)
else pi:=pointer(cardinal(CalcBuffer)+ofs);}
Result:=Boolean(pi^);
if not Result then exit;
if Buffer=nil then exit;
pi:=pointer(cardinal(pi)+1);
memcpy(pi,Buffer,FFieldsSize.Value[i]);
if Field.DataType=ftString
then pchar(cardinal(Buffer)+cardinal(FFieldsSize.Value[i]))^:=#0;
end;
procedure TVirtualDataSet.SetFieldData(Field: TField; Buffer: Pointer);
var
i :integer;
ofs :cardinal;
po:pointer;
begin
// if not (State in dsWriteModes) then DatabaseError(SNotEditing, Self);
Field.Validate(Buffer);
i:=GetFieldID(Field.FieldName);
ofs:=cardinal(FFieldsOffset.Value[i]);
if Assigned(FCalcBuf)
then po:=pointer(cardinal(FCalcBuf)+ofs)
else po:=pointer(cardinal(ActiveBuffer)+ofs);
{ if Assigned(FCalcBuf)
then po:=pointer(cardinal(FCalcBuf)+ofs)
else po:=pointer(cardinal(CalcBuffer)+ofs);}
if Buffer=nil then
begin
FillChar(po^,Integer(FFieldsSize.Value[i])+1,0);
if not (State in [dsBrowse, dsCalcFields, dsFilter, dsNewValue]) then
DataEvent(deFieldChange, Longint(Field));
exit;
end;
Boolean(po^):=True;
po:=pointer(cardinal(po)+1);
memcpy(Buffer,po,FFieldsSize.Value[i]);
if not (State in [dsBrowse, dsCalcFields, dsFilter, dsNewValue]) then
DataEvent(deFieldChange, Longint(Field));
end;
procedure TVirtualDataSet.InternalFirst;
var
accept : boolean;
begin
FCurrent:=-1;
//exit;
/////////////////////////////////////////////////
repeat
FCurrent:=FCurrent+1;
if FCurrent>=RecordCount then begin break;end;
accept:=true;
try
if Filtered and Assigned(FFilterRecordEvent) then
FFilterRecordEvent(self,FCurrent,accept);
except
on Exception do accept:=false;
end;
until accept;
// if FCurrent=0 then FCurrent:=-1;
dec(FCurrent);{roma}
end;
procedure TVirtualDataSet.InternalLast;
var
accept : boolean;
begin
VReadAll;
FCurrent:=RecordCount;
// exit;
//////////////////////////
repeat
FCurrent:=FCurrent-1;
if FCurrent<0 then break;
accept:=true;
try
if Filtered and Assigned(FFilterRecordEvent) then
FFilterRecordEvent(self,FCurrent,accept);
except
on Exception do accept:=false;
end;
until accept;
//if FCurrent=(RecordCount-1) then FCurrent:=RecordCount;
inc(FCurrent);
end;
procedure TVirtualDataSet.InternalHandleException;
begin
// MessageDlg('20',mtWarning,[mbOk],0);
raise Exception.Create('20'); {roma 14.12.2000}
end;
procedure TVirtualDataSet.ClearDataSet;
begin
end;
procedure TVirtualDataSet.SetFiltered(Value:boolean);
begin
inherited SetFiltered(Value);
if FOpened then Resync([]);// Refresh; {roma 13.08.2000}
end;
function TVirtualDataSet.Locate(const KeyFields: string; const KeyValues: Variant;
Options: TLocateOptions): Boolean;
var
FieldList:THArrayInteger;
sl1,sl2:TStrings;
p,i:integer;
Accept:boolean;
Bookm : integer;
function AnsiCompareCS(const v,w: string; CaseSensitive: boolean; PartialKey: boolean): boolean;
var s: string;
begin
if PartialKey
then s := Copy(w, 1, length(v))
else s := w;
if CaseSensitive
then Result := AnsiCompareStr(v,s)=0
else Result := AnsiCompareText(v,s)=0
end;
function Compare: boolean;
var i: integer;
begin
Result:=True;
for i:=0 to sl1.Count-1 do
if not AnsiCompareCS(sl1[i],sl2[i],not(loCaseInsensitive in Options),loPartialKey in Options) then begin
Result:=False;
exit;
end;
end;
procedure FillCurKeyValues;
var i:integer;
begin
sl2.Clear;
for i:=0 to FieldList.Count-1 do sl2.Add(VarToStr(GetFieldValue(p,FieldList[i])))
end;
function VGetFieldList(FieldList:THArrayInteger;const FieldNames:string):boolean;
var Pos,f:integer;
begin
Result:=True;
Pos:=1;
while Pos<=Length(FieldNames) do begin
Result:=True;
try
f:=GetFieldID(ExtractFieldName(FieldNames,Pos));
FieldList.AddValue(f);
except
Result:=False;
end;
end;
end;
begin
Result:=False;
FieldList:=THArrayInteger.Create;
sl1:=TStringList.Create;
sl2:=TStringList.Create;
try
if not VGetFieldList(FieldList,KeyFields) then exit;
if FieldList.Count=1
then sl1.Add(VarToStr(KeyValues))
else for i:=0 to FieldList.Count-1 do
sl1.Add(VarToStr(KeyValues[i]));
p:=0;
// VReadAll;
repeat
while p<RecordCount do begin
Accept:=True;
if Filtered and Assigned(FFilterRecordEvent)
then FFilterRecordEvent(self,p,Accept);
if Accept then begin
FillCurKeyValues;
Result:=Compare;
if Result then begin
Bookm:=FBookm.Value[p];
GotoBookmark(@Bookm);
exit;
end;
end;
inc(p);
end;
until not FetchNextBlock;
finally
sl2.Free;
sl1.Free;
FieldList.Free;
end;
end;
function TVirtualDataSet.Lookup(const KeyFields: string; const KeyValues: Variant;
const ResultFields: string): Variant;
var
FieldList:THArrayInteger;
sl1,sl2:TStrings;
p,i:integer;
Accept:boolean;
Bookm1 : TBookmark;
Bookm2 : integer;
function AnsiCompareCS(const v,w: string; CaseSensitive: boolean; PartialKey: boolean): boolean;
var s: string;
begin
if PartialKey
then s := Copy(w, 1, length(v))
else s := w;
if CaseSensitive
then Result := AnsiCompareStr(v,s)=0
else Result := AnsiCompareText(v,s)=0
end;
function Compare: boolean;
var i: integer;
begin
Result:=True;
for i:=0 to sl1.Count-1 do
if not AnsiCompareCS(sl1[i],sl2[i],True,False) then begin
Result:=False;
exit;
end;
end;
procedure FillCurKeyValues;
var i:integer;
begin
sl2.Clear;
for i:=0 to FieldList.Count-1 do sl2.Add(VarToStr(GetFieldValue(p,FieldList[i])))
end;
function VGetFieldList(FieldList:THArrayInteger;const FieldNames:string):boolean;
var Pos,f:integer;
begin
Result:=True;
Pos:=1;
while Pos<=Length(FieldNames) do begin
Result:=True;
try
f:=GetFieldID(ExtractFieldName(FieldNames,Pos));
FieldList.AddValue(f);
except
Result:=False;
end;
end;
end;
begin
Result:=Null;
FieldList:=THArrayInteger.Create;
sl1:=TStringList.Create;
sl2:=TStringList.Create;
try
if not VGetFieldList(FieldList,KeyFields) then exit;
if FieldList.Count=1
then sl1.Add(VarToStr(KeyValues))
else for i:=0 to FieldList.Count-1 do
sl1.Add(VarToStr(KeyValues[i]));
p:=0;
// VReadAll;
repeat
while p<RecordCount do begin
Accept:=True;
if Filtered and Assigned(FFilterRecordEvent)
then FFilterRecordEvent(self,p,Accept);
if Accept then begin
FillCurKeyValues;
if Compare then begin
Bookm1:=GetBookmark; //τα∩ε∞Φφασ∞ ≥σΩ≤∙σσ ∩εδεµσφΦσ
Bookm2:=FBookm.Value[p];
GotoBookmark(@Bookm2); // ∩σ≡σ⌡εΣΦ∞ φα φαΘΣσφ≤■ τα∩Φ±ⁿ
Result:=FieldValues[ResultFields]; // ταßΦ≡ασ∞ φαΘΣσφ√σ Σαφφ√σ
GotoBookmark(Bookm1); // ΓετΓ≡α∙ασ∞± εß≡α≥φε
exit;
end;
end;
inc(p);
end;
until not FetchNextBlock;
finally
sl2.Free;
sl1.Free;
FieldList.Free;
end;
end;
procedure TVirtualDataSet.ReOpen;
begin
Close;
Open;
end;
function TVirtualDataSet.CompareBookmarks(Bookmark1,
Bookmark2: TBookmark): integer;
const
RetCodes: array[Boolean, Boolean] of ShortInt = ((2,-1),(1,0));
begin
{ Check for uninitialized bookmarks }
Result := RetCodes[Bookmark1 = nil, Bookmark2 = nil];
if Result = 2 then begin
if PBookmInfo(Bookmark1).Bookmark<PBookmInfo(Bookmark2).Bookmark
then Result := -1
else if PBookmInfo(Bookmark1).Bookmark>PBookmInfo(Bookmark2).Bookmark
then Result := 1
else Result := 0;
end;
end;
procedure TVirtualDataSet.VReadAll;
begin
while FetchNextBlock do;
end;
procedure TVirtualDataSet.OpenAll;
begin
Open;
VReadAll;
end;
procedure TVirtualDataSet.InternalEdit;
begin
memcpy(ActiveBuffer,OldBuffer,RecordSize);
end;
procedure TVirtualDataSet.CopyStructure(DataSet: TDataSet);
var i:integer;
begin
FieldDefs.Clear;
for i:=0 to DataSet.FieldDefs.Count-1 do begin
FieldDefs.Add(DataSet.FieldDefs[i].Name,DataSet.FieldDefs[i].DataType,DataSet.FieldDefs[i].Size,DataSet.FieldDefs[i].Required);
end;
end;
end.