📄 ibcustomdataset.pas
字号:
FBase.OnTransactionFree := DoTransactionFree;
FLiveMode := [];
FRowsAffected := 0;
FStreamedActive := false;
if AOwner is TIBDatabase then
Database := TIBDatabase(AOwner)
else
if AOwner is TIBTransaction then
Transaction := TIBTransaction(AOwner);
end;
destructor TIBCustomDataSet.Destroy;
begin
if FIBLoaded then
begin
Close;
FreeAndNil(FDataLink);
FreeAndNil(FBase);
ClearBlobCache;
FreeAndNil(FBlobStreamList);
FreeMem(FBufferCache, 0);
FBufferCache := nil;
FreeMem(FOldBufferCache, 0);
FreeAndNil(FGeneratorField);
FOldBufferCache := nil;
FCacheSize := 0;
FOldCacheSize := 0;
FMappedFieldPosition := nil;
end;
inherited Destroy;
end;
function TIBCustomDataSet.AdjustCurrentRecord(Buffer: Pointer; GetMode: TGetMode):
TGetResult;
begin
while not IsVisible(Buffer) do
begin
if GetMode = gmPrior then
begin
Dec(FCurrentRecord);
if FCurrentRecord = -1 then
begin
result := grBOF;
exit;
end;
ReadRecordCache(FCurrentRecord, Buffer, False);
end
else
begin
Inc(FCurrentRecord);
if (FCurrentRecord = FRecordCount) then
begin
if (not FQSelect.EOF) and (FQSelect.Next <> nil) then
begin
FetchCurrentRecordToBuffer(FQSelect, FCurrentRecord, Buffer);
Inc(FRecordCount);
end
else
begin
result := grEOF;
exit;
end;
end
else
ReadRecordCache(FCurrentRecord, Buffer, False);
end;
end;
result := grOK;
end;
procedure TIBCustomDataSet.ApplyUpdates;
var
CurBookmark: string;
Buffer: PRecordData;
CurUpdateTypes: TIBUpdateRecordTypes;
UpdateAction: TIBUpdateAction;
UpdateKind: TUpdateKind;
bRecordsSkipped: Boolean;
procedure GetUpdateKind;
begin
case Buffer^.rdCachedUpdateStatus of
cusModified:
UpdateKind := ukModify;
cusInserted:
UpdateKind := ukInsert;
else
UpdateKind := ukDelete;
end;
end;
procedure ResetBufferUpdateStatus;
begin
case Buffer^.rdCachedUpdateStatus of
cusModified:
begin
PRecordData(Buffer)^.rdUpdateStatus := usUnmodified;
PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
end;
cusInserted:
begin
PRecordData(Buffer)^.rdUpdateStatus := usUnmodified;
PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
end;
cusDeleted:
begin
PRecordData(Buffer)^.rdUpdateStatus := usDeleted;
PRecordData(Buffer)^.rdCachedUpdateStatus := cusUnmodified;
end;
end;
WriteRecordCache(PRecordData(Buffer)^.rdRecordNumber, Pointer(Buffer));
end;
procedure UpdateUsingOnUpdateRecord;
begin
UpdateAction := uaFail;
try
FOnUpdateRecord(Self, UpdateKind, UpdateAction);
except
on E: Exception do
begin
if (E is EDatabaseError) and Assigned(FOnUpdateError) then
FOnUpdateError(Self, EIBError(E), UpdateKind, UpdateAction);
if UpdateAction = uaFail then
raise;
end;
end;
end;
procedure UpdateUsingUpdateObject;
begin
UpdateAction := uaApply;
try
FUpdateObject.Apply(UpdateKind);
ResetBufferUpdateStatus;
except
on E: Exception do
begin
UpdateAction := uaFail;
if (E is EDatabaseError) and Assigned(FOnUpdateError) then
FOnUpdateError(Self, EIBError(E), UpdateKind, UpdateAction);
end;
end;
end;
procedure UpdateUsingInternalquery;
begin
try
case Buffer^.rdCachedUpdateStatus of
cusModified:
InternalPostRecord(FQModify, Buffer);
cusInserted:
InternalPostRecord(FQInsert, Buffer);
cusDeleted:
InternalDeleteRecord(FQDelete, Buffer);
end;
except
on E: EIBError do begin
UpdateAction := uaFail;
if Assigned(FOnUpdateError) then
FOnUpdateError(Self, E, UpdateKind, UpdateAction);
case UpdateAction of
uaFail: raise;
uaAbort: SysUtils.Abort;
uaSkip: bRecordsSkipped := True;
end;
end;
end;
end;
begin
if State in [dsEdit, dsInsert] then
Post;
FBase.CheckDatabase;
FBase.CheckTransaction;
DisableControls;
CurBookmark := Bookmark;
CurUpdateTypes := FUpdateRecordTypes;
FUpdateRecordTypes := [cusModified, cusInserted, cusDeleted];
try
First;
bRecordsSkipped := False;
while not EOF do
begin
Buffer := PRecordData(GetActiveBuf);
GetUpdateKind;
UpdateAction := uaApply;
if Assigned(FUpdateObject) or Assigned(FOnUpdateRecord) then
begin
if (Assigned(FOnUpdateRecord)) then
UpdateUsingOnUpdateRecord
else
if Assigned(FUpdateObject) then
UpdateUsingUpdateObject;
case UpdateAction of
uaFail:
IBError(ibxeUserAbort, [nil]);
uaAbort:
SysUtils.Abort;
uaApplied:
ResetBufferUpdateStatus;
uaSkip:
bRecordsSkipped := True;
uaRetry:
Continue;
end;
end;
if (not Assigned(FUpdateObject)) and (UpdateAction = UaApply) then
begin
UpdateUsingInternalquery;
UpdateAction := uaApplied;
end;
Next;
end;
FUpdatesPending := bRecordsSkipped;
finally
FUpdateRecordTypes := CurUpdateTypes;
if BookmarkValid(Pointer(CurBookmark)) then
Bookmark := CurBookmark
else
First;
EnableControls;
end;
end;
procedure TIBCustomDataSet.InternalBatchInput(InputObject: TIBBatchInput);
begin
FQSelect.BatchInput(InputObject);
end;
procedure TIBCustomDataSet.InternalBatchOutput(OutputObject: TIBBatchOutput);
var
Qry: TIBSQL;
begin
Qry := TIBSQL.Create(Self);
try
Qry.Database := FBase.Database;
Qry.Transaction := FBase.Transaction;
Qry.SQL.Assign(FQSelect.SQL);
Qry.BatchOutput(OutputObject);
finally
Qry.Free;
end;
end;
procedure TIBCustomDataSet.CancelUpdates;
var
CurUpdateTypes: TIBUpdateRecordTypes;
begin
if State in [dsEdit, dsInsert] then
Cancel;
if FCachedUpdates and FUpdatesPending then
begin
DisableControls;
CurUpdateTypes := UpdateRecordTypes;
UpdateRecordTypes := [cusModified, cusInserted, cusDeleted];
try
First;
while not EOF do
begin
if UpdateStatus = usInserted then
RevertRecord
else
begin
RevertRecord;
Next;
end;
end;
finally
UpdateRecordTypes := CurUpdateTypes;
First;
FUpdatesPending := False;
EnableControls;
end;
end;
end;
procedure TIBCustomDataSet.ActivateConnection;
begin
if not Assigned(Database) then
IBError(ibxeDatabaseNotAssigned, [nil]);
if not Assigned(Transaction) then
IBError(ibxeTransactionNotAssigned, [nil]);
if not Database.Connected then Database.Open;
end;
function TIBCustomDataSet.ActivateTransaction: Boolean;
begin
Result := False;
if not Assigned(Transaction) then
IBError(ibxeTransactionNotAssigned, [nil]);
if not Transaction.Active then
begin
Result := True;
Transaction.StartTransaction;
end;
end;
procedure TIBCustomDataSet.DeactivateTransaction;
begin
if not Assigned(Transaction) then
IBError(ibxeTransactionNotAssigned, [nil]);
Transaction.CheckAutoStop;
end;
procedure TIBCustomDataSet.CheckDatasetClosed;
begin
if FOpen then
IBError(ibxeDatasetOpen, [nil]);
end;
procedure TIBCustomDataSet.CheckDatasetOpen;
begin
if not FOpen then
IBError(ibxeDatasetClosed, [nil]);
end;
procedure TIBCustomDataSet.CheckNotUniDirectional;
begin
if UniDirectional then
IBError(ibxeDataSetUniDirectional, [nil]);
end;
procedure TIBCustomDataSet.AdjustRecordOnInsert(Buffer: Pointer);
begin
with PRecordData(Buffer)^ do
if (State = dsInsert) and (not Modified) then
begin
rdRecordNumber := FRecordCount;
FCurrentRecord := FRecordCount;
end;
end;
function TIBCustomDataSet.CanEdit: Boolean;
var
Buff: PRecordData;
begin
Buff := PRecordData(GetActiveBuf);
result := ((FQModify.SQL.Text <> '') and (lmModify in FLiveMode)) or
(Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukModify).Text <> '')) or
((Buff <> nil) and (Buff^.rdCachedUpdateStatus = cusInserted) and
(FCachedUpdates));
end;
function TIBCustomDataSet.CanInsert: Boolean;
begin
result := ((FQInsert.SQL.Text <> '') and (lmInsert in FLiveMode)) or
(Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukInsert).Text <> ''));
end;
function TIBCustomDataSet.CanDelete: Boolean;
begin
if ((FQDelete.SQL.Text <> '') and (lmDelete in FLiveMode)) or
(Assigned(FUpdateObject) and (FUpdateObject.GetSQL(ukDelete).Text <> '')) then
result := True
else
result := False;
end;
function TIBCustomDataSet.CanRefresh: Boolean;
begin
result := ((FQRefresh.SQL.Text <> '') and (lmRefresh in FLiveMode)) or
(Assigned(FUpdateObject) and (FUpdateObject.RefreshSQL.Text <> ''));
end;
procedure TIBCustomDataSet.CheckEditState;
begin
case State of
{ Check all the wsEditMode types }
dsEdit, dsInsert, dsSetKey, dsCalcFields, dsFilter,
dsNewValue, dsInternalCalc :
begin
if (State in [dsEdit]) and (not CanEdit) then
IBError(ibxeCannotUpdate, [nil]);
if (State in [dsInsert]) and (not CanInsert) then
IBError(ibxeCannotInsert, [nil]);
end;
else
IBError(ibxeNotEditing, [])
end;
end;
procedure TIBCustomDataSet.ClearBlobCache;
var
i: Integer;
begin
for i := 0 to FBlobStreamList.Count - 1 do
begin
TIBBlobStream(FBlobStreamList[i]).Free;
FBlobStreamList[i] := nil;
end;
FBlobStreamList.Pack;
end;
procedure TIBCustomDataSet.CopyRecordBuffer(Source, Dest: Pointer);
begin
Move(Source^, Dest^, FRecordBufferSize);
end;
procedure TIBCustomDataSet.DoBeforeDatabaseDisconnect(Sender: TObject);
begin
if Active then
Active := False;
FInternalPrepared := False;
if Assigned(FBeforeDatabaseDisconnect) then
FBeforeDatabaseDisconnect(Sender);
end;
procedure TIBCustomDataSet.DoAfterDatabaseDisconnect(Sender: TObject);
begin
if Assigned(FAfterDatabaseDisconnect) then
FAfterDatabaseDisconnect(Sender);
end;
procedure TIBCustomDataSet.DoDatabaseFree(Sender: TObject);
begin
if Assigned(FDatabaseFree) then
FDatabaseFree(Sender);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -