I will try to explain an essence of a problem and its decision offered by me.
I use zeosdbo-6.5.1-alpha_cvs_13-10-2005 in DBS2007
In some cases I should edit at once some records containing in ZQuery, therefore I use CachedUpdates=True. After editing for record of changes in a DB I use the following code.
Code: Select all
conZC.StartTransaction;
try
qryZQ.ApplyUpdates;
...
qryZ.CommitUpdates;
conZC.Commit;
except
on E: Exception do begin
conZC.Rollback;
if Pos('duplicate key violates unique constraint ...', E.Message) > 0 then begin
...
Exit;
end;
Raise;
end;
end;
Code: Select all
//ZDbcCachedResultSet.pas
{**
Posts all saved updates to the server.
}
procedure TZAbstractCachedResultSet.PostUpdates;
var // + Dennica
i: integer; // + Dennica
begin
CheckClosed;
if FInitialRowsList.Count > 0 then
begin
i := 0; // + Dennica
// - Dennica while FInitialRowsList.Count > 0 do
while i < FInitialRowsList.Count do
begin
// - Dennica OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[0]);
// - Dennica NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[0]);
OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[i]); // + Dennica
NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[i]); // + Dennica
{ Updates default field values. }
if NewRowAccessor.RowBuffer.UpdateType = utInserted then
CalculateRowDefaults(NewRowAccessor);
{ Posts row updates and processes the exceptions. }
PostRowUpdates(OldRowAccessor, NewRowAccessor);
{ If post was Ok - update the row update type. }
// - Dennica if NewRowAccessor.RowBuffer.UpdateType <> utDeleted then
// - Dennica begin
// - Dennica NewRowAccessor.RowBuffer.UpdateType := utUnmodified;
// - Dennica if (FSelectedRow <> nil)
// - Dennica and (FSelectedRow.Index = NewRowAccessor.RowBuffer.Index) then
// - Dennica FSelectedRow.UpdateType := utUnmodified;
// - Dennica end;
{ Removes cached rows. }
// - Dennica OldRowAccessor.Dispose;
// - Dennica FInitialRowsList.Delete(0);
// - Dennica FCurrentRowsList.Delete(0);
Inc(i); // + Dennica
end;
end;
end;
{+ Dennica =)}
procedure TZAbstractCachedResultSet.CommitUpdates;
begin
CheckClosed;
if FInitialRowsList.Count > 0 then
begin
while FInitialRowsList.Count > 0 do
begin
OldRowAccessor.RowBuffer := PZRowBuffer(FInitialRowsList[0]);
NewRowAccessor.RowBuffer := PZRowBuffer(FCurrentRowsList[0]);
{ If post was Ok - update the row update type. }
if NewRowAccessor.RowBuffer.UpdateType <> utDeleted then
begin
NewRowAccessor.RowBuffer.UpdateType := utUnmodified;
if (FSelectedRow <> nil)
and (FSelectedRow.Index = NewRowAccessor.RowBuffer.Index) then
FSelectedRow.UpdateType := utUnmodified;
end;
{ Removes cached rows. }
OldRowAccessor.Dispose;
FInitialRowsList.Delete(0);
FCurrentRowsList.Delete(0);
end;
end;
end;
{**
Switched the cached updates mode.
@param Value boolean flag which turns on/off the cached updates mode.
}
procedure TZAbstractCachedResultSet.SetCachedUpdates(Value: Boolean);
begin
if FCachedUpdates <> Value then
begin
FCachedUpdates := Value;
if not FCachedUpdates then begin
PostUpdates;
CommitUpdates; // + Dennica
end;
end;
end;
{**
Inserts the contents of the insert row into this
<code>ResultSet</code> object and into the database.
The cursor must be on the insert row when this method is called.
}
procedure TZAbstractCachedResultSet.InsertRow;
var
TempRow: PZRowBuffer;
begin
CheckClosed;
{ Creates a new row. }
TempRow := FRowAccessor.RowBuffer;
FRowAccessor.Alloc;
FRowAccessor.MoveFrom(FInsertedRow);
FRowAccessor.RowBuffer^.UpdateType := utInserted;
FRowAccessor.RowBuffer^.Index := GetNextRowIndex;
AppendRow(FRowAccessor.RowBuffer);
{ Posts non-cached updates. }
if not FCachedUpdates then
begin
try
PostUpdates;
CommitUpdates; // + Dennica
except
on E: Exception do
begin
{ Restore the previous state. }
FRowAccessor.DisposeBuffer(FInitialRowsList[FInitialRowsList.Count - 1]);
FInitialRowsList.Delete(FInitialRowsList.Count - 1);
FRowAccessor.DisposeBuffer(FCurrentRowsList[FCurrentRowsList.Count - 1]);
FCurrentRowsList.Delete(FCurrentRowsList.Count - 1);
FRowAccessor.RowBuffer := TempRow;
{ Reraises the exception. }
RaiseSQLException(E);
end;
end;
end;
FRowsList.Add(FRowAccessor.RowBuffer);
LastRowNo := FRowsList.Count;
MoveAbsolute(LastRowNo);
end;
Code: Select all
//ZAbstractDataset.pas
{**
Clears cached updates buffer.
}
procedure TZAbstractDataset.CommitUpdates;
begin
CheckBrowseMode;
if CachedResultSet <> nil then
CachedResultSet.CommitUpdates;
// - Dennica CachedResultSet.CancelUpdates;
end;