浏览代码

--- Merging r21280 into '.':
U packages/fcl-db/tests/testbufdatasetstreams.pas
U packages/fcl-db/src/base/bufdataset.pas
--- Merging r21640 into '.':
U packages/fcl-db/tests/testspecifictbufdataset.pas
U packages/fcl-db/src/base/dataset.inc
--- Merging r21643 into '.':
U packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp
--- Merging r21674 into '.':
U packages/fcl-db/tests/bufdatasettoolsunit.pas

# revisions: 21280,21640,21643,21674
r21280 | marco | 2012-05-12 22:15:52 +0200 (Sat, 12 May 2012) | 11 lines
Changed paths:
M /trunk/packages/fcl-db/src/base/bufdataset.pas
M /trunk/packages/fcl-db/tests/testbufdatasetstreams.pas


Fix from Lacak2 for Mantis #21994 fixes

* when records are inserted into empty dataset and then all canceled by CancelUpdates AV is raised
* another fix for bug #18004, applied in rev.20531 (improved in rev.21197)
(original approach is not good because when record is inserted and deleted and again inserted,
then same memory block can be returned, which leads to confusion, because we get same BookmarkData for distinct records)
* +test
r21640 | joost | 2012-06-18 11:48:52 +0200 (Mon, 18 Jun 2012) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/base/dataset.inc
M /trunk/packages/fcl-db/tests/testspecifictbufdataset.pas

* Createdataset should not create fielddefs for calculated or lookup fields
r21643 | marco | 2012-06-18 13:15:18 +0200 (Mon, 18 Jun 2012) | 4 lines
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp

* do not set fregistered directoy since that hampers registerevents().
Patch by Ludo, Mantis #22244
r21674 | marco | 2012-06-21 17:31:21 +0200 (Thu, 21 Jun 2012) | 2 lines
Changed paths:
M /trunk/packages/fcl-db/tests/bufdatasettoolsunit.pas

* Add bufdataset support to testsuite for ftFixedChar and ftFmtBCD field types
mantis #22297 patch by Lacak2

git-svn-id: branches/fixes_2_6@22443 -

marco 13 年之前
父节点
当前提交
a57f3e4e38

+ 12 - 8
packages/fcl-db/src/base/bufdataset.pas

@@ -556,7 +556,7 @@ type
     Property AutoCalcFields;
     Property AutoCalcFields;
     Property Filter;
     Property Filter;
     Property Filtered;
     Property Filtered;
-    Property Readonly;
+    Property ReadOnly;
     Property AfterCancel;
     Property AfterCancel;
     Property AfterClose;
     Property AfterClose;
     Property AfterDelete;
     Property AfterDelete;
@@ -1181,6 +1181,8 @@ begin
       begin
       begin
       if assigned(OldValuesBuffer) then
       if assigned(OldValuesBuffer) then
         FreeRecordBuffer(OldValuesBuffer);
         FreeRecordBuffer(OldValuesBuffer);
+      if (UpdateKind = ukDelete) and assigned(BookmarkData.BookmarkData) then
+        FreeRecordBuffer(TRecordBuffer(BookmarkData.BookmarkData));
       end;
       end;
     end;
     end;
   SetLength(FUpdateBuffer,0);
   SetLength(FUpdateBuffer,0);
@@ -1916,7 +1918,7 @@ end;
 
 
 procedure TCustomBufDataset.InternalDelete;
 procedure TCustomBufDataset.InternalDelete;
 var i : Integer;
 var i : Integer;
-    RemRec, FreeRec : pointer;
+    RemRec : pointer;
     RemRecBookmrk : TBufBookmark;
     RemRecBookmrk : TBufBookmark;
 begin
 begin
   InternalSetToRecord(ActiveBuffer);
   InternalSetToRecord(ActiveBuffer);
@@ -1935,15 +1937,16 @@ begin
     FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
     FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
     move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
     move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
     end
     end
-  else //with FIndexes[0] do
+  else
     begin
     begin
     if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
     if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
       begin
       begin
       FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil;  //this 'disables' the updatebuffer
       FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil;  //this 'disables' the updatebuffer
-      FreeRec := RemRecBookmrk.BookmarkData;  // mantis #18004
-      FreeRecordBuffer(TRecordBuffer(FreeRec));
-      // RemRecBookmrk.BookmarkData still points to just freed record buffer
-      // There could be record in update-buffer, linked to this record
+      // Do NOT release record buffer (pointed by RemRecBookmrk.BookmarkData) here
+      //  - When record is inserted and deleted(and memory released) and again inserted then same memory block can be returned
+      //    which leads to confusion, because we get same BookmarkData for distinct records
+      //  - In CancelUpdates when records are restored it is expected, that deleted records still exists in memory
+      // There also could be record(s) in update-buffer, linked to this record.
       end;
       end;
     end;
     end;
   FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].NextBookmarkData);
   FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].NextBookmarkData);
@@ -2011,7 +2014,8 @@ var StoreRecBM     : TBufBookmark;
           begin
           begin
           GotoBookmark(@StoreRecBM);
           GotoBookmark(@StoreRecBM);
           if ScrollForward = grEOF then
           if ScrollForward = grEOF then
-            ScrollBackward;
+            if ScrollBackward = grBOF then
+              ScrollLast;  // last record will be removed from index, so move to spare record
           StoreCurrentRecIntoBookmark(@StoreRecBM);
           StoreCurrentRecIntoBookmark(@StoreRecBM);
           end;
           end;
         FCurrentIndex.RemoveRecordFromIndex(Bm);
         FCurrentIndex.RemoveRecordFromIndex(Bm);

+ 8 - 7
packages/fcl-db/src/base/dataset.inc

@@ -904,15 +904,16 @@ begin
     FieldDefs.BeginUpdate;
     FieldDefs.BeginUpdate;
     try
     try
       for i := 0 to Fields.Count-1 do with fields[i] do
       for i := 0 to Fields.Count-1 do with fields[i] do
-        begin
-        with TFieldDef.Create(FieldDefs,FieldName,DataType,Size,Required,i+1) do
+        if not (FieldKind in [fkCalculated,fkLookup]) then // Do not add fielddefs for calculated/lookup fields.
           begin
           begin
-          if Required then Attributes := attributes + [faRequired];
-          if ReadOnly then Attributes := attributes + [faReadOnly];
-          if DataType = ftBCD then precision := (fields[i] as TBCDField).Precision
-          else if DataType = ftFMTBcd then precision := (fields[i] as TFMTBCDField).Precision;
+          with TFieldDef.Create(FieldDefs,FieldName,DataType,Size,Required,FieldDefs.Count+1) do
+            begin
+            if Required then Attributes := attributes + [faRequired];
+            if ReadOnly then Attributes := attributes + [faReadOnly];
+            if DataType = ftBCD then precision := (fields[i] as TBCDField).Precision
+            else if DataType = ftFMTBcd then precision := (fields[i] as TFMTBCDField).Precision;
+            end;
           end;
           end;
-        end;
     finally
     finally
       FieldDefs.EndUpdate;
       FieldDefs.EndUpdate;
       end;
       end;

+ 0 - 1
packages/fcl-db/src/sqldb/postgres/pqeventmonitor.pp

@@ -122,7 +122,6 @@ end;
 
 
 procedure TPQEventMonitor.SetRegistered(AValue: Boolean);
 procedure TPQEventMonitor.SetRegistered(AValue: Boolean);
 begin
 begin
-  FRegistered := AValue;
   if not (csDesigning in ComponentState) then
   if not (csDesigning in ComponentState) then
     if AValue then
     if AValue then
       RegisterEvents
       RegisterEvents

+ 11 - 3
packages/fcl-db/tests/bufdatasettoolsunit.pas

@@ -37,6 +37,9 @@ type
 
 
 implementation
 implementation
 
 
+uses
+  StrUtils, FmtBCD;
+
 type
 type
 
 
   { TPersistentBufDataSet }
   { TPersistentBufDataSet }
@@ -85,6 +88,7 @@ var BufDataset  : TPersistentBufDataSet;
 
 
 begin
 begin
   BufDataset := TPersistentBufDataSet.Create(nil);
   BufDataset := TPersistentBufDataSet.Create(nil);
+  BufDataset.Name := 'NDataset';
   BufDataset.FieldDefs.Add('ID',ftInteger);
   BufDataset.FieldDefs.Add('ID',ftInteger);
   BufDataset.FieldDefs.Add('NAME',ftString,50);
   BufDataset.FieldDefs.Add('NAME',ftString,50);
   BufDataset.CreateDataset;
   BufDataset.CreateDataset;
@@ -109,20 +113,20 @@ var BufDataset  : TPersistentBufDataSet;
     i      : integer;
     i      : integer;
 
 
 begin
 begin
-  // Values >= 24:00:00.000 can't be handled by bufdataset
+  // Values >= 24:00:00.000 can't be handled by StrToTime function
   testTimeValues[2] := '23:59:59.000';
   testTimeValues[2] := '23:59:59.000';
   testTimeValues[3] := '23:59:59.003';
   testTimeValues[3] := '23:59:59.003';
 
 
   BufDataset := TPersistentBufDataSet.Create(nil);
   BufDataset := TPersistentBufDataSet.Create(nil);
   with BufDataset do
   with BufDataset do
     begin
     begin
+    Name := 'FieldDataset';
     UniDirectional := FUniDirectional;
     UniDirectional := FUniDirectional;
     FieldDefs.Add('ID',ftInteger);
     FieldDefs.Add('ID',ftInteger);
     FieldDefs.Add('FSTRING',ftString,10);
     FieldDefs.Add('FSTRING',ftString,10);
     FieldDefs.Add('FSMALLINT',ftSmallint);
     FieldDefs.Add('FSMALLINT',ftSmallint);
     FieldDefs.Add('FINTEGER',ftInteger);
     FieldDefs.Add('FINTEGER',ftInteger);
-    // Not supported by BufDataset:
-    // FieldDefs.Add('FWORD',ftWord);
+    FieldDefs.Add('FWORD',ftWord);
     FieldDefs.Add('FBOOLEAN',ftBoolean);
     FieldDefs.Add('FBOOLEAN',ftBoolean);
     FieldDefs.Add('FFLOAT',ftFloat);
     FieldDefs.Add('FFLOAT',ftFloat);
     FieldDefs.Add('FCURRENCY',ftCurrency);
     FieldDefs.Add('FCURRENCY',ftCurrency);
@@ -131,6 +135,8 @@ begin
     FieldDefs.Add('FTIME',ftTime);
     FieldDefs.Add('FTIME',ftTime);
     FieldDefs.Add('FDATETIME',ftDateTime);
     FieldDefs.Add('FDATETIME',ftDateTime);
     FieldDefs.Add('FLARGEINT',ftLargeint);
     FieldDefs.Add('FLARGEINT',ftLargeint);
+    FieldDefs.Add('FFIXEDCHAR',ftFixedChar,10);
+    FieldDefs.Add('FFMTBCD',ftFmtBCD);
     CreateDataset;
     CreateDataset;
     Open;
     Open;
     for i := 0 to testValuesCount-1 do
     for i := 0 to testValuesCount-1 do
@@ -147,6 +153,8 @@ begin
       FieldByName('FDATE').AsDateTime := StrToDateTime(testDateValues[i], Self.FormatSettings);
       FieldByName('FDATE').AsDateTime := StrToDateTime(testDateValues[i], Self.FormatSettings);
       FieldByName('FTIME').AsDateTime := StrToTime(testTimeValues[i], Self.FormatSettings);
       FieldByName('FTIME').AsDateTime := StrToTime(testTimeValues[i], Self.FormatSettings);
       FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
       FieldByName('FLARGEINT').AsLargeInt := testLargeIntValues[i];
+      FieldByName('FFIXEDCHAR').AsString := PadRight(testStringValues[i], 10);
+      FieldByName('FFMTBCD').AsBCD := StrToBCD(testFmtBCDValues[i], Self.FormatSettings);
       Post;
       Post;
     end;
     end;
     BufDataset.TempFileName:=GetTempFileName;
     BufDataset.TempFileName:=GetTempFileName;

+ 8 - 0
packages/fcl-db/tests/testbufdatasetstreams.pas

@@ -48,6 +48,7 @@ type
     procedure SeveralEditsCancelUpd;
     procedure SeveralEditsCancelUpd;
     procedure DeleteAllCancelUpd;
     procedure DeleteAllCancelUpd;
     procedure DeleteAllInsertCancelUpd;
     procedure DeleteAllInsertCancelUpd;
+    procedure AppendDeleteCancelUpd;
 
 
     procedure TestSimpleEditApplUpd;
     procedure TestSimpleEditApplUpd;
     procedure TestSimpleDeleteApplUpd;
     procedure TestSimpleDeleteApplUpd;
@@ -339,6 +340,7 @@ end;
 
 
 procedure TTestBufDatasetStreams.AppendDeleteChange(ADataset: TCustomBufDataset);
 procedure TTestBufDatasetStreams.AppendDeleteChange(ADataset: TCustomBufDataset);
 begin
 begin
+  // Tests bugs #19593, #21994
   with ADataset do
   with ADataset do
   begin
   begin
     AppendRecord([16,'TestName16']);
     AppendRecord([16,'TestName16']);
@@ -347,6 +349,7 @@ begin
     Prior;
     Prior;
     Delete;  // 15 update-buffer of deleted record is linked to 16
     Delete;  // 15 update-buffer of deleted record is linked to 16
     Delete;  // 16 inserted-deleted and linked by 15
     Delete;  // 16 inserted-deleted and linked by 15
+    AppendRecord([18,'TestName18']); // again append after delete
   end;
   end;
 end;
 end;
 
 
@@ -390,6 +393,11 @@ begin
   TestChangesCancelUpdates(@DeleteAllInsertChange);
   TestChangesCancelUpdates(@DeleteAllInsertChange);
 end;
 end;
 
 
+procedure TTestBufDatasetStreams.AppendDeleteCancelUpd;
+begin
+  TestChangesCancelUpdates(@AppendDeleteChange);
+end;
+
 procedure TTestBufDatasetStreams.TestBasicsXML;
 procedure TTestBufDatasetStreams.TestBasicsXML;
 var SaveDs: TCustomBufDataset;
 var SaveDs: TCustomBufDataset;
     LoadDs: TCustomBufDataset;
     LoadDs: TCustomBufDataset;

+ 47 - 0
packages/fcl-db/tests/testspecifictbufdataset.pas

@@ -32,6 +32,7 @@ type
   published
   published
     procedure CreateDatasetFromFielddefs;
     procedure CreateDatasetFromFielddefs;
     procedure CreateDatasetFromFields;
     procedure CreateDatasetFromFields;
+    procedure TestCreationDatasetWithCalcFields;
   end;
   end;
 
 
 implementation
 implementation
@@ -109,6 +110,52 @@ begin
   TestDataset(ds);
   TestDataset(ds);
 end;
 end;
 
 
+procedure TTestSpecificTBufDataset.TestCreationDatasetWithCalcFields;
+var ds : TBufDataset;
+    f: TField;
+    i: integer;
+begin
+  ds := TBufDataset.Create(nil);
+  try
+    F := TIntegerField.Create(ds);
+    F.FieldName:='ID';
+    F.DataSet:=ds;
+    F := TStringField.Create(ds);
+    F.FieldName:='NAME';
+    F.DataSet:=ds;
+    F.Size:=50;
+
+    F := TStringField.Create(ds);
+    F.FieldKind:=fkCalculated;
+    F.FieldName:='NAME_CALC';
+    F.DataSet:=ds;
+    F.Size:=50;
+
+    F := TStringField.Create(ds);
+    F.FieldKind:=fkLookup;
+    F.FieldName:='NAME_LKP';
+    F.LookupDataSet:=DBConnector.GetNDataset(5);
+    F.KeyFields:='ID';
+    F.LookupKeyFields:='ID';
+    F.LookupResultField:='NAME';
+    F.DataSet:=ds;
+    F.Size:=50;
+
+    DS.CreateDataset;
+
+    TestDataset(ds);
+
+    for i := 0 to ds.FieldDefs.Count-1 do
+      begin
+      CheckNotEquals(ds.FieldDefs[i].Name,'NAME_CALC');
+      CheckNotEquals(ds.FieldDefs[i].Name,'NAME_LKP');
+      end;
+    DS.Close;
+  finally
+    ds.Free;
+  end;
+end;
+
 initialization
 initialization
 {$ifdef fpc}
 {$ifdef fpc}