mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-16 21:26:30 +02:00
1907 lines
37 KiB
PHP
1907 lines
37 KiB
PHP
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2000 by Michael Van Canneyt, member of the
|
|
Free Pascal development team
|
|
|
|
Dataset implementation
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
{ ---------------------------------------------------------------------
|
|
TDataSet
|
|
---------------------------------------------------------------------}
|
|
|
|
Const
|
|
DefaultBufferCount = 10;
|
|
|
|
constructor TDataSet.Create(AOwner: TComponent);
|
|
|
|
begin
|
|
Inherited Create(AOwner);
|
|
FFieldDefs:=TFieldDefs.Create(Self);
|
|
FFieldList:=TFields.Create(Self);
|
|
FDataSources:=TList.Create;
|
|
end;
|
|
|
|
|
|
|
|
destructor TDataSet.Destroy;
|
|
|
|
var
|
|
i: Integer;
|
|
|
|
begin
|
|
Active:=False;
|
|
FFieldDefs.Free;
|
|
FFieldList.Free;
|
|
With FDatasources do
|
|
begin
|
|
While Count>0 do
|
|
TDatasource(Items[Count - 1]).DataSet:=Nil;
|
|
Free;
|
|
end;
|
|
if Assigned(FBuffers) then
|
|
begin
|
|
for i := 0 to FBufferCount do
|
|
FreeRecordBuffer(FBuffers[i]);
|
|
FreeMem(FBuffers);
|
|
end;
|
|
Inherited Destroy;
|
|
end;
|
|
|
|
// This procedure must be called when the first record is made/read
|
|
Procedure TDataset.ActivateBuffers;
|
|
|
|
begin
|
|
FBOF:=False;
|
|
FEOF:=False;
|
|
FActiveRecord:=0;
|
|
end;
|
|
|
|
Procedure TDataset.UpdateFieldDefs;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.BindFields(Binding: Boolean);
|
|
|
|
var i, FieldIndex: Integer;
|
|
FieldDef: TFieldDef;
|
|
begin
|
|
{
|
|
Here some magic will be needed later; for now just simply set
|
|
Just set fieldno from listindex...
|
|
Later we should take it from the fielddefs.
|
|
// ATM Set by CreateField ...
|
|
For I:=0 to FFieldList.Count-1 do
|
|
FFieldList[i].FFieldNo:=I;
|
|
}
|
|
FCalcFieldsSize := 0;
|
|
FBlobFieldCount := 0;
|
|
for i := 0 to Fields.Count - 1 do
|
|
with Fields[i] do begin
|
|
if Binding then begin
|
|
if FieldKind in [fkCalculated, fkLookup] then begin
|
|
FFieldNo := -1;
|
|
FOffset := FCalcFieldsSize;
|
|
Inc(FCalcFieldsSize, DataSize + 1);
|
|
if FieldKind in [fkLookup] then begin
|
|
if ((FLookupDataSet = nil) or (FLookupKeyFields = '') or
|
|
(FLookupResultField = '') or (FKeyFields = '')) then
|
|
DatabaseErrorFmt(SLookupInfoError, [DisplayName]);
|
|
FFields.CheckFieldNames(FKeyFields);
|
|
FLookupDataSet.Fields.CheckFieldNames(FLookupKeyFields);
|
|
FLookupDataSet.FieldByName(FLookupResultField);
|
|
if FLookupCache then RefreshLookupList;
|
|
end
|
|
end else begin
|
|
FieldDef := nil;
|
|
FieldIndex := FieldDefs.IndexOf(Fields[i].FieldName);
|
|
if FieldIndex <> -1 then begin
|
|
FieldDef := FieldDefs[FieldIndex];
|
|
FFieldNo := FieldDef.FieldNo;
|
|
if IsBlob then begin
|
|
FSize := FieldDef.Size;
|
|
FOffset := FBlobFieldCount;
|
|
Inc(FBlobFieldCount);
|
|
end;
|
|
end else FFieldNo := FieldIndex;
|
|
end;
|
|
end else FFieldNo := 0;;
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.BookmarkAvailable: Boolean;
|
|
|
|
Const BookmarkStates = [dsBrowse,dsEdit,dsInsert];
|
|
|
|
begin
|
|
Result:=(Not IsEmpty) and (State in BookmarkStates)
|
|
and (getBookMarkFlag(ActiveBuffer)=bfCurrent);
|
|
end;
|
|
|
|
Procedure TDataset.CalculateFields(Buffer: PChar);
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FCalcBuffer := Buffer;
|
|
if (State <> dsInternalCalc) and (IsUniDirectional = False) then
|
|
begin
|
|
ClearCalcFields(CalcBuffer);
|
|
for I := 0 to Fields.Count - 1 do
|
|
with Fields[I] do
|
|
if FieldKind = fkLookup then CalcLookupValue;
|
|
end;
|
|
DoOnCalcFields;
|
|
end;
|
|
|
|
Procedure TDataset.CheckActive;
|
|
|
|
begin
|
|
If Not Active then
|
|
DataBaseError(SInactiveDataset);
|
|
end;
|
|
|
|
Procedure TDataset.CheckInactive;
|
|
|
|
begin
|
|
If Active then
|
|
DataBaseError(SActiveDataset);
|
|
end;
|
|
|
|
Procedure TDataset.ClearBuffers;
|
|
|
|
begin
|
|
FRecordCount:=0;
|
|
FactiveRecord:=0;
|
|
FCurrentRecord:=-1;
|
|
FBOF:=True;
|
|
FEOF:=True;
|
|
end;
|
|
|
|
Procedure TDataset.ClearCalcFields(Buffer: PChar);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.CloseBlob(Field: TField);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.CloseCursor;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.CreateFields;
|
|
|
|
Var I : longint;
|
|
|
|
begin
|
|
{$ifdef DSDebug}
|
|
Writeln ('Creating fields');
|
|
Writeln ('Count : ',fielddefs.Count);
|
|
For I:=0 to FieldDefs.Count-1 do
|
|
Writeln('Def ',I,' : ',Fielddefs.items[i].Name,'(',Fielddefs.items[i].FieldNo,')');
|
|
{$endif}
|
|
For I:=0 to fielddefs.Count-1 do
|
|
With Fielddefs.Items[I] do
|
|
If DataType<>ftUnknown then
|
|
begin
|
|
{$ifdef DSDebug}
|
|
Writeln('About to create field',FieldDefs.Items[i].Name);
|
|
{$endif}
|
|
CreateField(self);
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.DataEvent(Event: TDataEvent; Info: Ptrint);
|
|
|
|
Var
|
|
i : longint;
|
|
|
|
begin
|
|
// Do some bookkeeping;
|
|
case Event of
|
|
deFieldChange: begin
|
|
if TField(Info).FieldKind in [fkData,fkInternalCalc] then
|
|
SetModified(True);
|
|
if State <> dsSetKey then begin
|
|
if FInternalCalcFields and (TField(Info).FieldKind = fkData) then
|
|
RefreshInternalCalcFields(ActiveBuffer)
|
|
else if (FCalcFieldsSize <> 0) and FAutoCalcFields and
|
|
(TField(Info).FieldKind = fkData) then
|
|
CalculateFields(ActiveBuffer);
|
|
TField(Info).Change;
|
|
end;
|
|
end;
|
|
deDataSetChange, deDataSetScroll:
|
|
if State <> dsInsert then UpdateCursorPos;
|
|
end;
|
|
// Distribute event to datasets;
|
|
if FDisableControlsCount = 0 then
|
|
for I := 0 to FDataSources.Count - 1 do
|
|
TDataSource(FDataSources[I]).ProcessEvent(Event, Info);
|
|
end;
|
|
|
|
Procedure TDataset.DestroyFields;
|
|
|
|
begin
|
|
FFieldList.Clear;
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterCancel;
|
|
|
|
begin
|
|
If assigned(FAfterCancel) then
|
|
FAfterCancel(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterClose;
|
|
|
|
begin
|
|
If assigned(FAfterClose) then
|
|
FAfterClose(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterDelete;
|
|
|
|
begin
|
|
If assigned(FAfterDelete) then
|
|
FAfterDelete(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterEdit;
|
|
|
|
begin
|
|
If assigned(FAfterEdit) then
|
|
FAfterEdit(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterInsert;
|
|
|
|
begin
|
|
If assigned(FAfterInsert) then
|
|
FAfterInsert(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterOpen;
|
|
|
|
begin
|
|
If assigned(FAfterOpen) then
|
|
FAfterOpen(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterPost;
|
|
|
|
begin
|
|
If assigned(FAfterPost) then
|
|
FAfterPost(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoAfterScroll;
|
|
|
|
begin
|
|
If assigned(FAfterScroll) then
|
|
FAfterScroll(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeCancel;
|
|
|
|
begin
|
|
If assigned(FBeforeCancel) then
|
|
FBeforeCancel(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeClose;
|
|
|
|
begin
|
|
If assigned(FBeforeClose) then
|
|
FBeforeClose(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeDelete;
|
|
|
|
begin
|
|
If assigned(FBeforeDelete) then
|
|
FBeforeDelete(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeEdit;
|
|
|
|
begin
|
|
If assigned(FBeforeEdit) then
|
|
FBeforeEdit(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeInsert;
|
|
|
|
begin
|
|
If assigned(FBeforeInsert) then
|
|
FBeforeInsert(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeOpen;
|
|
|
|
begin
|
|
If assigned(FBeforeOpen) then
|
|
FBeforeOpen(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforePost;
|
|
|
|
begin
|
|
If assigned(FBeforePost) then
|
|
FBeforePost(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoBeforeScroll;
|
|
|
|
begin
|
|
If assigned(FBeforeScroll) then
|
|
FBeforeScroll(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoInternalOpen;
|
|
|
|
begin
|
|
FDefaultFields:=FieldCount=0;
|
|
DoBeforeOpen;
|
|
Try
|
|
{$ifdef dsdebug}
|
|
Writeln ('Calling internal open');
|
|
{$endif}
|
|
InternalOpen;
|
|
FBOF:=True;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Calling RecalcBufListSize');
|
|
{$endif}
|
|
FRecordcount := 0;
|
|
RecalcBufListSize;
|
|
FEOF := (FRecordcount = 0);
|
|
{$ifdef dsdebug}
|
|
Writeln ('Setting state to browse');
|
|
{$endif}
|
|
SetState(dsBrowse);
|
|
DoAfterOpen;
|
|
DoAfterScroll;
|
|
except
|
|
DoInternalClose(false);
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.DoInternalClose(DoCheck : Boolean);
|
|
|
|
begin
|
|
if DoCheck then
|
|
CheckBrowsemode;
|
|
FreeFieldBuffers;
|
|
ClearBuffers;
|
|
SetBufListSize(-1);
|
|
SetState(dsInactive);
|
|
InternalClose;
|
|
end;
|
|
|
|
Procedure TDataset.DoOnCalcFields;
|
|
|
|
begin
|
|
If assigned(FOnCalcfields) then
|
|
FOnCalcFields(Self);
|
|
end;
|
|
|
|
Procedure TDataset.DoOnNewRecord;
|
|
|
|
begin
|
|
If assigned(FOnNewRecord) then
|
|
FOnNewRecord(Self);
|
|
end;
|
|
|
|
Function TDataset.FieldByNumber(FieldNo: Longint): TField;
|
|
|
|
begin
|
|
Result:=FFieldList.FieldByNumber(FieldNo);
|
|
end;
|
|
|
|
Function TDataset.FindRecord(Restart, GoForward: Boolean): Boolean;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.FreeFieldBuffers;
|
|
|
|
Var I : longint;
|
|
|
|
begin
|
|
For I:=0 to FFieldList.Count-1 do
|
|
FFieldList[i].FreeBuffers;
|
|
end;
|
|
|
|
Function TDataset.GetBookmarkStr: TBookmarkStr;
|
|
|
|
begin
|
|
Result:='';
|
|
If BookMarkAvailable then
|
|
begin
|
|
SetLength(Result,FBookMarkSize);
|
|
GetBookMarkData(ActiveBuffer,Pointer(Result));
|
|
end
|
|
end;
|
|
|
|
Function TDataset.GetBuffer (Index : longint) : Pchar;
|
|
|
|
begin
|
|
Result:=FBuffers[Index];
|
|
end;
|
|
|
|
Procedure TDataset.GetCalcFields(Buffer: PChar);
|
|
|
|
var
|
|
dss: TDataSetState;
|
|
begin
|
|
if (FCalcFieldsSize > 0) or FInternalCalcFields then
|
|
begin
|
|
dss := FState;
|
|
FState := dsCalcFields;
|
|
try
|
|
CalculateFields(Buffer);
|
|
finally
|
|
FState := dss;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.GetCanModify: Boolean;
|
|
|
|
begin
|
|
Result:= not FIsUnidirectional;
|
|
end;
|
|
|
|
Procedure TDataset.GetChildren(Proc: TGetChildProc; Root: TComponent);
|
|
|
|
var
|
|
I: Integer;
|
|
Field: TField;
|
|
|
|
begin
|
|
for I := 0 to Fields.Count - 1 do begin
|
|
Field := Fields[I];
|
|
if (Field.Owner = Root) then
|
|
Proc(Field);
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.GetDataSource: TDataSource;
|
|
begin
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TDataSet.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
|
|
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TDataSet.GetFieldData(Field: TField; Buffer: Pointer;
|
|
NativeFormat: Boolean): Boolean;
|
|
|
|
begin
|
|
Result := GetFieldData(Field, Buffer);
|
|
end;
|
|
|
|
procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer);
|
|
|
|
begin
|
|
// empty procedure
|
|
end;
|
|
|
|
procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer;
|
|
NativeFormat: Boolean);
|
|
|
|
begin
|
|
SetFieldData(Field, Buffer);
|
|
end;
|
|
|
|
Function TDataset.GetField (Index : Longint) : TField;
|
|
|
|
begin
|
|
Result:=FFIeldList[index];
|
|
end;
|
|
|
|
Function TDataset.GetFieldClass(FieldType: TFieldType): TFieldClass;
|
|
|
|
begin
|
|
Result := DefaultFieldClasses[FieldType];
|
|
end;
|
|
|
|
Function TDataset.GetIsIndexField(Field: TField): Boolean;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
|
|
Function TDataset.GetNextRecord: Boolean;
|
|
|
|
procedure ExchangeBuffers(var buf1,buf2 : pointer);
|
|
|
|
var tempbuf : pointer;
|
|
|
|
begin
|
|
tempbuf := buf1;
|
|
buf1 := buf2;
|
|
buf2 := tempbuf;
|
|
end;
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('Getting next record. Internal RecordCount : ',FRecordCount);
|
|
{$endif}
|
|
If FRecordCount>0 Then SetCurrentRecord(FRecordCount-1);
|
|
Result:=GetRecord(FBuffers[FBuffercount],gmNext,True)=grOK;
|
|
|
|
if result then
|
|
begin
|
|
If FRecordCount=0 then ActivateBuffers;
|
|
if FRecordcount=FBuffercount then
|
|
shiftbuffersbackward
|
|
else
|
|
begin
|
|
inc(FRecordCount);
|
|
FCurrentRecord:=FRecordCount - 1;
|
|
ExchangeBuffers(Fbuffers[FCurrentRecord],FBuffers[FBuffercount]);
|
|
end;
|
|
end
|
|
else
|
|
cursorposchanged;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Result getting next record : ',Result);
|
|
{$endif}
|
|
end;
|
|
|
|
Function TDataset.GetNextRecords: Longint;
|
|
|
|
begin
|
|
Result:=0;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Getting next record(s), need :',FBufferCount);
|
|
{$endif}
|
|
While (FRecordCount<FBufferCount) and GetNextRecord do
|
|
Inc(Result);
|
|
{$ifdef dsdebug}
|
|
Writeln ('Result Getting next record(S), GOT :',RESULT);
|
|
{$endif}
|
|
end;
|
|
|
|
Function TDataset.GetPriorRecord: Boolean;
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('GetPriorRecord: Getting previous record');
|
|
{$endif}
|
|
If FRecordCount>0 Then SetCurrentRecord(0);
|
|
Result:=GetRecord(FBuffers[FBuffercount],gmPrior,True)=grOK;
|
|
if result then
|
|
begin
|
|
If FRecordCount=0 then ActivateBuffers;
|
|
shiftbuffersforward;
|
|
|
|
if FRecordcount<FBuffercount then
|
|
inc(FRecordCount);
|
|
end
|
|
else
|
|
cursorposchanged;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Result getting prior record : ',Result);
|
|
{$endif}
|
|
end;
|
|
|
|
Function TDataset.GetPriorRecords: Longint;
|
|
|
|
begin
|
|
Result:=0;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Getting previous record(s), need :',FBufferCount);
|
|
{$endif}
|
|
While (FRecordCount<FbufferCount) and GetPriorRecord do
|
|
Inc(Result);
|
|
end;
|
|
|
|
Function TDataset.GetRecNo: Longint;
|
|
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
Function TDataset.GetRecordCount: Longint;
|
|
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
Procedure TDataset.InitFieldDefs;
|
|
|
|
begin
|
|
if IsCursorOpen then InternalInitFieldDefs
|
|
else
|
|
try
|
|
OpenCursor(True);
|
|
finally
|
|
CloseCursor;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.InitRecord(Buffer: PChar);
|
|
|
|
begin
|
|
InternalInitRecord(Buffer);
|
|
ClearCalcFields(Buffer);
|
|
end;
|
|
|
|
Procedure TDataset.InternalCancel;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.InternalEdit;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.InternalRefresh;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.OpenCursor(InfoQuery: Boolean);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.RefreshInternalCalcFields(Buffer: PChar);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.SetTempState(const Value: TDataSetState): TDataSetState;
|
|
|
|
begin
|
|
result := FState;
|
|
FState := value;
|
|
inc(FDisableControlsCount);
|
|
end;
|
|
|
|
Procedure TDataset.RestoreState(const Value: TDataSetState);
|
|
|
|
begin
|
|
FState := value;
|
|
dec(FDisableControlsCount);
|
|
end;
|
|
|
|
function TDataset.GetActive : boolean;
|
|
|
|
begin
|
|
result := FState <> dsInactive;
|
|
end;
|
|
|
|
Procedure TDataset.InternalHandleException;
|
|
|
|
begin
|
|
if assigned(classes.ApplicationHandleException) then
|
|
classes.ApplicationHandleException(self)
|
|
else
|
|
ShowException(ExceptObject,ExceptAddr);
|
|
end;
|
|
|
|
Procedure TDataset.SetActive (Value : Boolean);
|
|
|
|
begin
|
|
if value and (Fstate = dsInactive) then
|
|
begin
|
|
if csLoading in ComponentState then
|
|
begin
|
|
FOpenAfterRead := true;
|
|
exit;
|
|
end
|
|
else
|
|
DoInternalOpen;
|
|
end
|
|
else if not value and (Fstate <> dsinactive) then
|
|
DoInternalClose(True);
|
|
end;
|
|
|
|
procedure TDataset.Loaded;
|
|
|
|
begin
|
|
inherited;
|
|
try
|
|
if FOpenAfterRead then SetActive(true);
|
|
except
|
|
if csDesigning in Componentstate then
|
|
InternalHandleException
|
|
else
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDataSet.RecalcBufListSize;
|
|
|
|
var
|
|
i, j, ABufferCount: Integer;
|
|
DataLink: TDataLink;
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln('Recalculating buffer list size - check cursor');
|
|
{$endif}
|
|
If Not IsCursorOpen Then
|
|
Exit;
|
|
{$ifdef dsdebug}
|
|
Writeln('Recalculating buffer list size');
|
|
{$endif}
|
|
ABufferCount := DefaultBufferCount;
|
|
for i := 0 to FDataSources.Count - 1 do
|
|
for j := 0 to TDataSource(FDataSources[i]).DataLinks.Count - 1 do
|
|
begin
|
|
DataLink:=TDataLink(TDataSource(FDataSources[i]).DataLinks[j]);
|
|
if DataLink.BufferCount>ABufferCount then
|
|
ABufferCount:=DataLink.BufferCount;
|
|
end;
|
|
|
|
If (FBufferCount=ABufferCount) Then
|
|
exit;
|
|
|
|
{$ifdef dsdebug}
|
|
Writeln('Setting buffer list size');
|
|
{$endif}
|
|
|
|
SetBufListSize(ABufferCount);
|
|
{$ifdef dsdebug}
|
|
Writeln('Getting next buffers');
|
|
{$endif}
|
|
GetNextRecords;
|
|
{$Ifdef dsDebug}
|
|
WriteLn(
|
|
'SetBufferCount: FActiveRecord=',FActiveRecord,
|
|
' FCurrentRecord=',FCurrentRecord,
|
|
' FBufferCount= ',FBufferCount,
|
|
' FRecordCount=',FRecordCount);
|
|
{$Endif}
|
|
end;
|
|
|
|
Procedure TDataset.SetBookmarkStr(const Value: TBookmarkStr);
|
|
|
|
begin
|
|
GotoBookMark(Pointer(Value))
|
|
end;
|
|
|
|
Procedure TDataset.SetBufListSize(Value: Longint);
|
|
|
|
Var I : longint;
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('SetBufListSize: ',Value);
|
|
{$endif}
|
|
If Value=FBufferCount Then
|
|
exit;
|
|
If Value>FBufferCount then
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln (' Reallocating memory :',(Value+1)*SizeOf(PChar));
|
|
{$endif}
|
|
ReAllocMem(FBuffers,(Value+1)*SizeOf(PChar));
|
|
{$ifdef dsdebug}
|
|
Writeln (' Filling memory :',(Value+1-FBufferCount)*SizeOf(PChar));
|
|
{$endif}
|
|
if FBufferCount > 0 then inc(FBufferCount); // Cause FBuffers[FBufferCount] is already allocated
|
|
FillChar(FBuffers[FBufferCount],(Value+1-FBufferCount)*SizeOF(Pchar),#0);
|
|
{$ifdef dsdebug}
|
|
Writeln (' Filled memory :');
|
|
{$endif}
|
|
Try
|
|
{$ifdef dsdebug}
|
|
Writeln (' Assigning buffers :',(Value)*SizeOf(PChar));
|
|
{$endif}
|
|
For I:=FBufferCount to Value do
|
|
FBuffers[i]:=AllocRecordBuffer;
|
|
{$ifdef dsdebug}
|
|
Writeln (' Assigned buffers ',FBufferCount,' :',(Value)*SizeOf(PChar));
|
|
{$endif}
|
|
except
|
|
I:=FBufferCount;
|
|
While (I<(Value+1)) and (FBuffers[i]<>Nil) do
|
|
begin
|
|
FreeRecordBuffer(FBuffers[i]);
|
|
Inc(i);
|
|
end;
|
|
raise;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln (' Freeing buffers :',FBufferCount-Value);
|
|
{$endif}
|
|
if (value > -1) and (FActiveRecord>Value-1) then
|
|
begin
|
|
for i := 0 to (FActiveRecord-Value) do
|
|
shiftbuffersbackward;
|
|
FActiverecord := Value -1;
|
|
end;
|
|
|
|
If Assigned(FBuffers) then
|
|
begin
|
|
For I:=Value+1 to FBufferCount do
|
|
FreeRecordBuffer(FBuffers[i]);
|
|
ReAllocMem(FBuffers,(Value+1)*SizeOf(Pchar));
|
|
end;
|
|
if FRecordcount > Value then FRecordcount := Value;
|
|
end;
|
|
If Value=-1 then
|
|
Value:=0;
|
|
FBufferCount:=Value;
|
|
{$ifdef dsdebug}
|
|
Writeln (' SetBufListSize: Final FBufferCount=',FBufferCount);
|
|
{$endif}
|
|
end;
|
|
|
|
Procedure TDataset.SetChildOrder(Component: TComponent; Order: Longint);
|
|
|
|
var
|
|
Field: TField;
|
|
begin
|
|
Field := Component as TField;
|
|
if Fields.IndexOf(Field) >= 0 then
|
|
Field.Index := Order;
|
|
end;
|
|
|
|
Procedure TDataset.SetCurrentRecord(Index: Longint);
|
|
|
|
begin
|
|
If FCurrentRecord<>Index then
|
|
begin
|
|
{$ifdef DSdebug}
|
|
Writeln ('Setting current record to',index);
|
|
{$endif}
|
|
Case GetBookMarkFlag(FBuffers[Index]) of
|
|
bfCurrent : InternalSetToRecord(FBuffers[Index]);
|
|
bfBOF : InternalFirst;
|
|
bfEOF : InternalLast;
|
|
end;
|
|
FCurrentRecord:=index;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.SetField (Index : Longint;Value : TField);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.SetFilterOptions(Value: TFilterOptions);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.SetFilterText(const Value: string);
|
|
|
|
begin
|
|
FFilterText := value;
|
|
end;
|
|
|
|
Procedure TDataset.SetFiltered(Value: Boolean);
|
|
|
|
begin
|
|
FFiltered := value;
|
|
end;
|
|
|
|
Procedure TDataset.SetFound(const Value: Boolean);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.SetModified(Value: Boolean);
|
|
|
|
begin
|
|
FModified := value;
|
|
end;
|
|
|
|
Procedure TDataset.SetName(const Value: TComponentName);
|
|
|
|
function CheckName(FieldName: string): string;
|
|
var i,j: integer;
|
|
begin
|
|
Result := FieldName;
|
|
i := 0;
|
|
j := 0;
|
|
while (i < Fields.Count) do begin
|
|
if Result = Fields[i].FieldName then begin
|
|
inc(j);
|
|
Result := FieldName + IntToStr(j);
|
|
end else Inc(i);
|
|
end;
|
|
end;
|
|
var i: integer;
|
|
nm: string;
|
|
old: string;
|
|
begin
|
|
if Self.Name = Value then Exit;
|
|
old := Self.Name;
|
|
inherited SetName(Value);
|
|
if (csDesigning in ComponentState) then
|
|
for i := 0 to Fields.Count - 1 do begin
|
|
nm := old + Fields[i].FieldName;
|
|
if Copy(Fields[i].Name, 1, Length(nm)) = nm then
|
|
Fields[i].Name := CheckName(Value + Fields[i].FieldName);
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.SetOnFilterRecord(const Value: TFilterRecordEvent);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.SetRecNo(Value: Longint);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.SetState(Value: TDataSetState);
|
|
|
|
begin
|
|
If Value<>FState then
|
|
begin
|
|
FState:=Value;
|
|
DataEvent(deUpdateState,0);
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.Tempbuffer: PChar;
|
|
|
|
begin
|
|
Result := FBuffers[FRecordCount];
|
|
end;
|
|
|
|
Procedure TDataset.UpdateIndexDefs;
|
|
|
|
begin
|
|
// Empty Abstract
|
|
end;
|
|
|
|
Function TDataset.ControlsDisabled: Boolean;
|
|
|
|
|
|
begin
|
|
Result := (FDisableControlsCount > 0);
|
|
end;
|
|
|
|
Function TDataset.ActiveBuffer: PChar;
|
|
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('Active buffer requested. Returning:',ActiveRecord);
|
|
{$endif}
|
|
Result:=FBuffers[FActiveRecord];
|
|
end;
|
|
|
|
Procedure TDataset.Append;
|
|
|
|
begin
|
|
DoInsertAppend(True);
|
|
end;
|
|
|
|
Procedure TDataset.InternalInsert;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.AppendRecord(const Values: array of const);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.BookmarkValid(ABookmark: TBookmark): Boolean;
|
|
{
|
|
Should be overridden by descendant objects.
|
|
}
|
|
begin
|
|
Result:=False
|
|
end;
|
|
|
|
Procedure TDataset.Cancel;
|
|
|
|
begin
|
|
If State in [dsEdit,dsInsert] then
|
|
begin
|
|
DataEvent(deCheckBrowseMode,0);
|
|
DoBeforeCancel;
|
|
UpdateCursorPos;
|
|
InternalCancel;
|
|
FreeFieldBuffers;
|
|
if (state = dsInsert) and (FRecordcount = 1) then
|
|
begin
|
|
FEOF := true;
|
|
FBOF := true;
|
|
FRecordcount := 0;
|
|
SetState(dsBrowse);
|
|
DataEvent(deDatasetChange,0);
|
|
end
|
|
else
|
|
begin
|
|
SetState(dsBrowse);
|
|
SetCurrentRecord(FActiverecord);
|
|
resync([]);
|
|
end;
|
|
DoAfterCancel;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.CheckBrowseMode;
|
|
|
|
begin
|
|
CheckActive;
|
|
DataEvent(deCheckBrowseMode,0);
|
|
Case State of
|
|
dsedit,dsinsert: begin
|
|
UpdateRecord;
|
|
If Modified then Post else Cancel;
|
|
end;
|
|
dsSetKey: Post;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.ClearFields;
|
|
|
|
|
|
begin
|
|
DataEvent(deCheckBrowseMode, 0);
|
|
FreeFieldBuffers;
|
|
InternalInitRecord(ActiveBuffer);
|
|
if State <> dsSetKey then GetCalcFields(ActiveBuffer);
|
|
DataEvent(deRecordChange, 0);
|
|
end;
|
|
|
|
Procedure TDataset.Close;
|
|
|
|
begin
|
|
Active:=False;
|
|
end;
|
|
|
|
Function TDataset.CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint;
|
|
|
|
begin
|
|
Result:=0;
|
|
end;
|
|
|
|
Function TDataset.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream;
|
|
|
|
|
|
begin
|
|
Result:=Nil;
|
|
end;
|
|
|
|
Procedure TDataset.CursorPosChanged;
|
|
|
|
|
|
begin
|
|
FCurrentRecord:=-1;
|
|
end;
|
|
|
|
Procedure TDataset.Delete;
|
|
|
|
|
|
begin
|
|
If Not CanModify then
|
|
DatabaseError(SDatasetReadOnly,Self);
|
|
if State in [dsInsert] then
|
|
begin
|
|
Cancel;
|
|
end else begin
|
|
DataEvent(deCheckBrowseMode,0);
|
|
{$ifdef dsdebug}
|
|
writeln ('Delete: checking required fields');
|
|
{$endif}
|
|
DoBeforeDelete;
|
|
DoBeforeScroll;
|
|
If Not TryDoing(@InternalDelete,OnPostError) then exit;
|
|
{$ifdef dsdebug}
|
|
writeln ('Delete: Internaldelete succeeded');
|
|
{$endif}
|
|
FreeFieldBuffers;
|
|
SetState(dsBrowse);
|
|
{$ifdef dsdebug}
|
|
writeln ('Delete: Browse mode set');
|
|
{$endif}
|
|
SetCurrentRecord(FActiverecord);
|
|
Resync([]);
|
|
DoAfterDelete;
|
|
DoAfterScroll;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.DisableControls;
|
|
|
|
|
|
begin
|
|
If FDisableControlsCount=0 then
|
|
begin
|
|
{ Save current state,
|
|
needed to detect change of state when enabling controls.
|
|
}
|
|
FDisableControlsState:=FState;
|
|
FEnableControlsEvent:=deDatasetChange;
|
|
end;
|
|
Inc(FDisableControlsCount);
|
|
end;
|
|
|
|
Procedure TDataset.DoInsertAppend(DoAppend : Boolean);
|
|
|
|
|
|
procedure DoInsert;
|
|
|
|
Var BookBeforeInsert : TBookmarkStr;
|
|
TempBuf : pointer;
|
|
|
|
begin
|
|
// need to scroll up al buffers after current one,
|
|
// but copy current bookmark to insert buffer.
|
|
If FRecordcount > 0 then
|
|
BookBeforeInsert:=Bookmark;
|
|
|
|
if FActiveRecord < FRecordCount-1 then
|
|
begin
|
|
TempBuf := FBuffers[FBuffercount];
|
|
move(FBuffers[FActiveRecord],FBuffers[FActiveRecord+1],(Fbuffercount-FActiveRecord)*sizeof(FBuffers[0]));
|
|
FBuffers[FActiveRecord]:=TempBuf;
|
|
end
|
|
else if FRecordcount=FBuffercount then
|
|
shiftbuffersbackward
|
|
else begin
|
|
if FRecordCount>0 then
|
|
inc(FActiveRecord);
|
|
end;
|
|
|
|
// Active buffer is now edit buffer. Initialize.
|
|
InitRecord(FBuffers[FActiveRecord]);
|
|
cursorposchanged;
|
|
|
|
// Put bookmark in edit buffer.
|
|
if FRecordCount=0 then
|
|
begin
|
|
fEOF := false;
|
|
SetBookmarkFlag(ActiveBuffer,bfBOF)
|
|
end
|
|
else
|
|
begin
|
|
fBOF := false;
|
|
// 29:01:05, JvdS: Why is this here?!? It can result in records with the same bookmark-data?
|
|
// I would say that the 'internalinsert' should do this. But I don't know how Tdbf handles it
|
|
if FRecordcount > 0 then
|
|
SetBookMarkData(ActiveBuffer,pointer(BookBeforeInsert));
|
|
end;
|
|
|
|
InternalInsert;
|
|
|
|
// update buffer count.
|
|
If FRecordCount<FBufferCount then
|
|
Inc(FRecordCount);
|
|
end;
|
|
|
|
begin
|
|
If Not CanModify then
|
|
DatabaseError(SDatasetReadOnly,Self);
|
|
CheckBrowseMode;
|
|
DoBeforeInsert;
|
|
DoBeforeScroll;
|
|
If Not DoAppend then
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('going to insert mode');
|
|
{$endif}
|
|
|
|
DoInsert;
|
|
end
|
|
else
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('going to append mode');
|
|
{$endif}
|
|
ClearBuffers;
|
|
InternalLast;
|
|
GetPriorRecords;
|
|
if FRecordCount>0 then
|
|
FActiveRecord:=FRecordCount-1;
|
|
DoInsert;
|
|
SetBookmarkFlag(ActiveBuffer,bfEOF);
|
|
FBOF :=False;
|
|
FEOF := true;
|
|
end;
|
|
SetState(dsInsert);
|
|
try
|
|
DoOnNewRecord;
|
|
except
|
|
SetCurrentRecord(FActiverecord);
|
|
resync([]);
|
|
raise;
|
|
end;
|
|
// mark as not modified.
|
|
FModified:=False;
|
|
// Final events.
|
|
DataEvent(deDatasetChange,0);
|
|
DoAfterInsert;
|
|
DoAfterScroll;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Done with append');
|
|
{$endif}
|
|
end;
|
|
|
|
Procedure TDataset.Edit;
|
|
|
|
begin
|
|
If Not CanModify then
|
|
DatabaseError(SDatasetReadOnly,Self);
|
|
If State in [dsedit,dsinsert] then exit;
|
|
If FRecordCount = 0 then
|
|
begin
|
|
Append;
|
|
Exit;
|
|
end;
|
|
CheckBrowseMode;
|
|
DoBeforeEdit;
|
|
If Not TryDoing(@InternalEdit,OnEditError) then
|
|
exit;
|
|
GetCalcFields(ActiveBuffer);
|
|
SetState(dsedit);
|
|
DataEvent(deRecordChange,0);
|
|
DoAfterEdit;
|
|
end;
|
|
|
|
Procedure TDataset.EnableControls;
|
|
|
|
|
|
begin
|
|
If FDisableControlsCount>0 then
|
|
begin
|
|
Dec(FDisableControlsCount);
|
|
If FDisableControlsCount=0 then
|
|
begin
|
|
// State changed since disablecontrols ?
|
|
If FDisableControlsState<>FState then
|
|
DataEvent(deUpdateState,0);
|
|
If (FDisableControlsState<>dsInactive) and (FState<>dsInactive) then
|
|
DataEvent(FEnableControlsEvent,0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.FieldByName(const FieldName: string): TField;
|
|
|
|
|
|
begin
|
|
Result:=FindField(FieldName);
|
|
If Result=Nil then
|
|
DatabaseErrorFmt(SFieldNotFound,[FieldName],Self);
|
|
end;
|
|
|
|
Function TDataset.FindField(const FieldName: string): TField;
|
|
|
|
|
|
begin
|
|
Result:=FFieldList.FindField(FieldName);
|
|
end;
|
|
|
|
Function TDataset.FindFirst: Boolean;
|
|
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.FindLast: Boolean;
|
|
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.FindNext: Boolean;
|
|
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.FindPrior: Boolean;
|
|
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Procedure TDataset.First;
|
|
|
|
|
|
begin
|
|
CheckBrowseMode;
|
|
DoBeforeScroll;
|
|
ClearBuffers;
|
|
try
|
|
InternalFirst;
|
|
GetNextRecords;
|
|
finally
|
|
FBOF:=True;
|
|
DataEvent(deDatasetChange,0);
|
|
DoAfterScroll;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.FreeBookmark(ABookmark: TBookmark);
|
|
|
|
|
|
begin
|
|
FreeMem(ABookMark,FBookMarkSize);
|
|
end;
|
|
|
|
Function TDataset.GetBookmark: TBookmark;
|
|
|
|
|
|
begin
|
|
if BookmarkAvailable then
|
|
begin
|
|
GetMem (Result,FBookMarkSize);
|
|
GetBookMarkdata(ActiveBuffer,Result);
|
|
end
|
|
else
|
|
Result:=Nil;
|
|
end;
|
|
|
|
Function TDataset.GetCurrentRecord(Buffer: PChar): Boolean;
|
|
|
|
|
|
begin
|
|
Result:=False;
|
|
end;
|
|
|
|
Procedure TDataset.GetFieldList(List: TList; const FieldNames: string);
|
|
|
|
Function NextName(Var S : String) : String;
|
|
|
|
Var
|
|
P : integer;
|
|
|
|
begin
|
|
P:=Pos(';',S);
|
|
If (P=0) then
|
|
P:=Length(S)+1;
|
|
Result:=Copy(S,1,P-1);
|
|
system.Delete(S,1,P);
|
|
end;
|
|
|
|
var
|
|
F: TField;
|
|
Names,N : String;
|
|
|
|
begin
|
|
Names:=FieldNames;
|
|
N:=Nextname(Names);
|
|
while (N<>'') do
|
|
begin
|
|
F:=FieldByName(N);
|
|
If Assigned(List) then
|
|
List.Add(F);
|
|
N:=NextName(Names);
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.GetFieldNames(List: TStrings);
|
|
|
|
|
|
begin
|
|
FFieldList.GetFieldNames(List);
|
|
end;
|
|
|
|
Procedure TDataset.GotoBookmark(ABookmark: TBookmark);
|
|
|
|
|
|
begin
|
|
If Assigned(ABookMark) then
|
|
begin
|
|
CheckBrowseMode;
|
|
DoBeforeScroll;
|
|
InternalGotoBookMark(ABookMark);
|
|
Resync([rmExact,rmCenter]);
|
|
DoAfterScroll;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.Insert;
|
|
|
|
begin
|
|
DoInsertAppend(False);
|
|
end;
|
|
|
|
Procedure TDataset.InsertRecord(const Values: array of const);
|
|
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.IsEmpty: Boolean;
|
|
|
|
begin
|
|
Result:=(Bof and Eof);
|
|
end;
|
|
|
|
Function TDataset.IsLinkedTo(DataSource: TDataSource): Boolean;
|
|
|
|
begin
|
|
//!! Not tested, I never used nested DS
|
|
if (DataSource = nil) or (DataSource.Dataset = nil) then begin
|
|
Result := False
|
|
end else if DataSource.Dataset = Self then begin
|
|
Result := True;
|
|
end else begin
|
|
Result := DataSource.Dataset.IsLinkedTo(DataSource.Dataset.DataSource);
|
|
end;
|
|
//!! DataSetField not implemented
|
|
end;
|
|
|
|
Function TDataset.IsSequenced: Boolean;
|
|
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
Procedure TDataset.Last;
|
|
|
|
begin
|
|
CheckBrowseMode;
|
|
DoBeforeScroll;
|
|
ClearBuffers;
|
|
try
|
|
InternalLast;
|
|
GetPriorRecords;
|
|
if FRecordCount>0 then
|
|
FActiveRecord:=FRecordCount-1
|
|
finally
|
|
FEOF:=true;
|
|
DataEvent(deDataSetChange, 0);
|
|
DoAfterScroll;
|
|
end;
|
|
end;
|
|
|
|
Function TDataset.MoveBy(Distance: Longint): Longint;
|
|
Var
|
|
TheResult: Integer;
|
|
|
|
Function Scrollforward : Integer;
|
|
|
|
begin
|
|
Result:=0;
|
|
{$ifdef dsdebug}
|
|
Writeln('Scrolling forward :',Distance);
|
|
Writeln('Active buffer : ',FActiveRecord);
|
|
Writeln('RecordCount : ',FRecordCount);
|
|
WriteLn('BufferCount : ',FBufferCount);
|
|
{$endif}
|
|
FBOF:=False;
|
|
While (Distance>0) and not FEOF do
|
|
begin
|
|
If FActiveRecord<FRecordCount-1 then
|
|
begin
|
|
Inc(FActiveRecord);
|
|
Dec(Distance);
|
|
Inc(TheResult); //Inc(Result);
|
|
end
|
|
else
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln('Moveby : need next record');
|
|
{$endif}
|
|
If GetNextRecord then
|
|
begin
|
|
Dec(Distance);
|
|
Dec(Result);
|
|
Inc(TheResult); //Inc(Result);
|
|
end
|
|
else
|
|
FEOF:=true;
|
|
end;
|
|
end
|
|
end;
|
|
Function ScrollBackward : Integer;
|
|
|
|
begin
|
|
if FIsUniDirectional then DatabaseError(SUniDirectional);
|
|
Result:=0;
|
|
{$ifdef dsdebug}
|
|
Writeln('Scrolling backward:',Abs(Distance));
|
|
Writeln('Active buffer : ',FActiveRecord);
|
|
Writeln('RecordCunt : ',FRecordCount);
|
|
WriteLn('BufferCount : ',FBufferCount);
|
|
{$endif}
|
|
FEOF:=False;
|
|
While (Distance<0) and not FBOF do
|
|
begin
|
|
If FActiveRecord>0 then
|
|
begin
|
|
Dec(FActiveRecord);
|
|
Inc(Distance);
|
|
Dec(TheResult); //Dec(Result);
|
|
end
|
|
else
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln('Moveby : need next record');
|
|
{$endif}
|
|
If GetPriorRecord then
|
|
begin
|
|
Inc(Distance);
|
|
Inc(Result);
|
|
Dec(TheResult); //Dec(Result);
|
|
end
|
|
else
|
|
FBOF:=true;
|
|
end;
|
|
end
|
|
end;
|
|
|
|
Var
|
|
Scrolled : Integer;
|
|
|
|
begin
|
|
CheckBrowseMode;
|
|
Result:=0; TheResult:=0;
|
|
If ((Distance>0) and FEOF) or
|
|
((Distance<0) and FBOF) then
|
|
exit;
|
|
DoBeforeScroll;
|
|
Try
|
|
Scrolled := 0;
|
|
If Distance>0 then
|
|
Scrolled:=ScrollForward
|
|
else
|
|
Scrolled:=ScrollBackward;
|
|
finally
|
|
{$ifdef dsdebug}
|
|
WriteLn('ActiveRecord=', FActiveRecord,' FEOF=',FEOF,' FBOF=',FBOF);
|
|
{$Endif}
|
|
// If FRecordCount<>PrevRecordCount then
|
|
if Scrolled = 0 then
|
|
DataEvent(deDatasetChange,0)
|
|
else
|
|
DataEvent(deDatasetScroll,Scrolled);
|
|
DoAfterScroll;
|
|
Result:=TheResult;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.Next;
|
|
|
|
begin
|
|
MoveBy(1);
|
|
end;
|
|
|
|
Procedure TDataset.Open;
|
|
|
|
begin
|
|
Active:=True;
|
|
end;
|
|
|
|
Procedure TDataset.Post;
|
|
|
|
Procedure Checkrequired;
|
|
|
|
Var I : longint;
|
|
|
|
begin
|
|
For I:=0 to FFieldList.Count-1 do
|
|
With FFieldList[i] do
|
|
// Required fields that are NOT autoinc !! Autoinc cannot be set !!
|
|
if Required and not ReadOnly and
|
|
(FieldKind=fkData) and Not (DataType=ftAutoInc) then
|
|
DatabaseErrorFmt(SNeedField,[DisplayName],Self);
|
|
end;
|
|
|
|
begin
|
|
if State in [dsEdit,dsInsert] then
|
|
begin
|
|
DataEvent(deUpdateRecord,0);
|
|
DataEvent(deCheckBrowseMode,0);
|
|
{$ifdef dsdebug}
|
|
writeln ('Post: checking required fields');
|
|
{$endif}
|
|
CheckRequired;
|
|
DoBeforePost;
|
|
If Not TryDoing(@InternalPost,OnPostError) then exit;
|
|
cursorposchanged;
|
|
{$ifdef dsdebug}
|
|
writeln ('Post: Internalpost succeeded');
|
|
{$endif}
|
|
FreeFieldBuffers;
|
|
// First set the state to dsBrowse, then the Resync, to prevent the calling of
|
|
// the deDatasetChange event, while the state is still 'editable', while the db isn't
|
|
SetState(dsBrowse);
|
|
Resync([]);
|
|
{$ifdef dsdebug}
|
|
writeln ('Post: Browse mode set');
|
|
{$endif}
|
|
DoAfterPost;
|
|
end;
|
|
end;
|
|
|
|
Procedure TDataset.Prior;
|
|
|
|
begin
|
|
MoveBy(-1);
|
|
end;
|
|
|
|
Procedure TDataset.Refresh;
|
|
|
|
begin
|
|
CheckbrowseMode;
|
|
UpdateCursorPos;
|
|
InternalRefresh;
|
|
SetCurrentRecord(FActiverecord);
|
|
Resync([]);
|
|
end;
|
|
|
|
Procedure TDataset.RegisterDataSource(ADatasource : TDataSource);
|
|
|
|
begin
|
|
FDatasources.Add(ADataSource);
|
|
RecalcBufListSize;
|
|
end;
|
|
|
|
|
|
Procedure TDataset.Resync(Mode: TResyncMode);
|
|
|
|
var i,count : integer;
|
|
|
|
begin
|
|
// See if we can find the requested record.
|
|
{$ifdef dsdebug}
|
|
Writeln ('Resync called');
|
|
{$endif}
|
|
|
|
// place the cursor of the underlying dataset to the active record
|
|
// SetCurrentRecord(FActiverecord);
|
|
|
|
// Now look if the data on the current cursor of the underlying dataset is still available
|
|
If GetRecord(Fbuffers[0],gmcurrent,False)<>grOk Then
|
|
// If that fails and rmExact is set, then raise an exception
|
|
If rmExact in Mode then
|
|
DatabaseError(SNoSuchRecord,Self)
|
|
// else, if rmexact is not set, try to fetch the next or prior record in the underlying dataset
|
|
else if (GetRecord(Fbuffers[0],gmnext,True)<>grOk) and
|
|
(GetRecord(Fbuffers[0],gmprior,True)<>grOk) then
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('Resync: fuzzy resync');
|
|
{$endif}
|
|
// nothing found, invalidate buffer and bail out.
|
|
ClearBuffers;
|
|
DataEvent(deDatasetChange,0);
|
|
exit;
|
|
end;
|
|
FCurrentRecord := 0;
|
|
FEOF := false;
|
|
FBOF := false;
|
|
|
|
// If we've arrived here, FBuffer[0] is the current record
|
|
If (rmCenter in Mode) then
|
|
count := (FRecordCount div 2)
|
|
else
|
|
count := FActiveRecord;
|
|
i := 0;
|
|
FRecordcount := 1;
|
|
FActiveRecord := 0;
|
|
|
|
// Fill the buffers before the active record
|
|
while (i < count) and GetPriorRecord do
|
|
inc(i);
|
|
FActiveRecord := i;
|
|
// Fill the rest of the buffer
|
|
getnextrecords;
|
|
// If the buffer is not full yet, try to fetch some more prior records
|
|
if FRecordcount < FBuffercount then inc(FActiverecord,getpriorrecords);
|
|
// That's all folks!
|
|
DataEvent(deDatasetChange,0);
|
|
end;
|
|
|
|
Procedure TDataset.SetFields(const Values: array of const);
|
|
|
|
Var I : longint;
|
|
begin
|
|
For I:=0 to high(Values) do
|
|
Fields[I].AssignValue(Values[I]);
|
|
end;
|
|
|
|
Function TDataset.Translate(Src, Dest: PChar; ToOem: Boolean): Integer;
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function Tdataset.TryDoing (P : TDataOperation; Ev : TDatasetErrorEvent) : Boolean;
|
|
|
|
Var Retry : TDataAction;
|
|
|
|
begin
|
|
{$ifdef dsdebug}
|
|
Writeln ('Trying to do');
|
|
If P=Nil then writeln ('Procedure to call is nil !!!');
|
|
{$endif dsdebug}
|
|
Result:=True;
|
|
Retry:=daRetry;
|
|
while Retry=daRetry do
|
|
Try
|
|
{$ifdef dsdebug}
|
|
Writeln ('Trying : updatecursorpos');
|
|
{$endif dsdebug}
|
|
UpdateCursorPos;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Trying to do it');
|
|
{$endif dsdebug}
|
|
P;
|
|
exit;
|
|
except
|
|
On E : EDatabaseError do
|
|
begin
|
|
retry:=daFail;
|
|
If Assigned(Ev) then
|
|
Ev(Self,E,Retry);
|
|
Case Retry of
|
|
daFail : Raise;
|
|
daAbort : Result:=False;
|
|
end;
|
|
end;
|
|
else
|
|
Raise;
|
|
end;
|
|
{$ifdef dsdebug}
|
|
Writeln ('Exit Trying to do');
|
|
{$endif dsdebug}
|
|
end;
|
|
|
|
Procedure TDataset.UpdateCursorPos;
|
|
|
|
begin
|
|
If FRecordCount>0 then
|
|
SetCurrentRecord(FactiveRecord);
|
|
end;
|
|
|
|
Procedure TDataset.UpdateRecord;
|
|
|
|
begin
|
|
if not (State in dsEditModes) then
|
|
DatabaseError(SNotInEditState, Self);
|
|
DataEvent(deUpdateRecord, 0);
|
|
end;
|
|
|
|
Function TDataSet.UpdateStatus: TUpdateStatus;
|
|
|
|
begin
|
|
Result:=usUnmodified;
|
|
end;
|
|
|
|
Procedure TDataset.RemoveField (Field : TField);
|
|
|
|
begin
|
|
//!! To be implemented
|
|
end;
|
|
|
|
Function TDataset.Getfieldcount : Longint;
|
|
|
|
begin
|
|
Result:=FFieldList.Count;
|
|
end;
|
|
|
|
Procedure TDataset.ShiftBuffersBackward;
|
|
|
|
var TempBuf : pointer;
|
|
|
|
begin
|
|
TempBuf := FBuffers[0];
|
|
move(FBuffers[1],FBuffers[0],(fbuffercount)*sizeof(FBuffers[0]));
|
|
FBuffers[buffercount]:=TempBuf;
|
|
end;
|
|
|
|
Procedure TDataset.ShiftBuffersForward;
|
|
|
|
var TempBuf : pointer;
|
|
|
|
begin
|
|
TempBuf := FBuffers[FBufferCount];
|
|
move(FBuffers[0],FBuffers[1],(fbuffercount)*sizeof(FBuffers[0]));
|
|
FBuffers[0]:=TempBuf;
|
|
end;
|
|
|
|
function TDataset.GetFieldValues(Fieldname: string): Variant;
|
|
|
|
var i: Integer;
|
|
FieldList: TList;
|
|
begin
|
|
if Pos(';', FieldName) <> 0 then begin
|
|
FieldList := TList.Create;
|
|
try
|
|
GetFieldList(FieldList, FieldName);
|
|
Result := VarArrayCreate([0, FieldList.Count - 1], varVariant);
|
|
for i := 0 to FieldList.Count - 1 do
|
|
Result[i] := TField(FieldList[i]).Value;
|
|
finally
|
|
FieldList.Free;
|
|
end;
|
|
end else
|
|
Result := FieldByName(FieldName).Value
|
|
end;
|
|
|
|
procedure TDataset.SetFieldValues(Fieldname: string; Value: Variant);
|
|
|
|
var i: Integer;
|
|
FieldList: TList;
|
|
begin
|
|
if Pos(';', FieldName) <> 0 then
|
|
begin
|
|
FieldList := TList.Create;
|
|
try
|
|
GetFieldList(FieldList, FieldName);
|
|
for i := 0 to FieldList.Count - 1 do
|
|
TField(FieldList[i]).Value := Value[i];
|
|
finally
|
|
FieldList.Free;
|
|
end;
|
|
end else
|
|
FieldByName(FieldName).Value := Value;
|
|
end;
|
|
|
|
Function TDataset.Locate(const keyfields: string; const keyvalues: Variant; options: TLocateOptions) : boolean;
|
|
|
|
begin
|
|
if fIsUnidirectional then
|
|
DataBaseError(SUniDirectional);
|
|
Result := False;
|
|
end;
|
|
|
|
Function TDataset.Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant;
|
|
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
|
|
Procedure TDataset.UnRegisterDataSource(ADatasource : TDatasource);
|
|
|
|
begin
|
|
FDataSources.Remove(ADataSource);
|
|
end;
|
|
|