Browse Source

+ implemented calculated fieds + test

git-svn-id: trunk@5775 -
joost 18 years ago
parent
commit
280520c0f7
3 changed files with 108 additions and 30 deletions
  1. 49 29
      fcl/db/bufdataset.pp
  2. 2 1
      fcl/db/dataset.inc
  3. 57 0
      fcl/dbtests/testdbbasics.pas

+ 49 - 29
fcl/db/bufdataset.pp

@@ -216,7 +216,7 @@ end;
 
 
 function TBufDataset.AllocRecordBuffer: PChar;
 function TBufDataset.AllocRecordBuffer: PChar;
 begin
 begin
-  result := AllocMem(FRecordsize + sizeof(TBufBookmark));
+  result := AllocMem(FRecordsize + sizeof(TBufBookmark) + CalcfieldsSize);
 // The records are initialised, or else the fields of an empty, just-opened dataset
 // The records are initialised, or else the fields of an empty, just-opened dataset
 // are not null
 // are not null
   InitRecord(result);
   InitRecord(result);
@@ -514,6 +514,7 @@ end;
 function TBufDataset.GetCurrentBuffer: PChar;
 function TBufDataset.GetCurrentBuffer: PChar;
 begin
 begin
   if State = dsFilter then Result := FFilterBuffer
   if State = dsFilter then Result := FFilterBuffer
+  else if state = dsCalcFields then Result := CalcBuffer
   else Result := ActiveBuffer;
   else Result := ActiveBuffer;
 end;
 end;
 
 
@@ -530,37 +531,49 @@ var CurrBuff : pchar;
 
 
 begin
 begin
   Result := False;
   Result := False;
-  If Field.Fieldno > 0 then // If = 0, then calculated field or something similar
+  if state = dsOldValue then
     begin
     begin
-    if state = dsOldValue then
+    if not GetRecordUpdateBuffer then
       begin
       begin
-      if not GetRecordUpdateBuffer then
-        begin
-        // There is no old value available
-        result := false;
-        exit;
-        end;
-      currbuff := FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer+sizeof(TBufRecLinkItem);
-      end
-    else
+      // There is no old value available
+      result := false;
+      exit;
+      end;
+    currbuff := FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer+sizeof(TBufRecLinkItem);
+    end
+  else
+    begin
+    CurrBuff := GetCurrentBuffer;
+    if not assigned(CurrBuff) then
       begin
       begin
-      CurrBuff := GetCurrentBuffer;
-      if not assigned(CurrBuff) then
-        begin
-        result := false;
-        exit;
-        end;
+      result := false;
+      exit;
       end;
       end;
+    end;
 
 
+  If Field.Fieldno > 0 then // If = 0, then calculated field or something similar
+    begin
     if GetFieldIsnull(pbyte(CurrBuff),Field.Fieldno-1) then
     if GetFieldIsnull(pbyte(CurrBuff),Field.Fieldno-1) then
       begin
       begin
       result := false;
       result := false;
       exit;
       exit;
       end;
       end;
-
-    inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]);
-    if assigned(buffer) then Move(CurrBuff^, Buffer^, GetFieldSize(FieldDefs[Field.FieldNo-1]));
+    if assigned(buffer) then
+      begin
+      inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]);
+      Move(CurrBuff^, Buffer^, GetFieldSize(FieldDefs[Field.FieldNo-1]));
+      end;
     Result := True;
     Result := True;
+    end
+  else
+    begin
+    Inc(CurrBuff, GetRecordSize + Field.Offset);
+    Result := Boolean(CurrBuff^);
+    if result and assigned(Buffer) then
+      begin
+      inc(CurrBuff);
+      Move(CurrBuff^, Buffer^, Field.Datasize);
+      end;
     end;
     end;
 end;
 end;
 
 
@@ -581,12 +594,12 @@ begin
     DatabaseErrorFmt(SNotInEditState,[Name],self);
     DatabaseErrorFmt(SNotInEditState,[Name],self);
     exit;
     exit;
     end;
     end;
-//  If Field.Fieldno > 0 then // If = 0, then calculated field or something
+  if state = dsFilter then  // Set the value into the 'temporary' FLastRecBuf buffer for Locate and Lookup
+    CurrBuff := pointer(FLastRecBuf) + sizeof(TBufRecLinkItem)
+  else
+    CurrBuff := GetCurrentBuffer;
+  If Field.Fieldno > 0 then // If = 0, then calculated field or something
     begin
     begin
-    if state = dsFilter then  // Set the value into the 'temporary' FLastRecBuf buffer for Locate and Lookup
-      CurrBuff := pointer(FLastRecBuf) + sizeof(TBufRecLinkItem)
-    else
-      CurrBuff := ActiveBuffer;
     NullMask := CurrBuff;
     NullMask := CurrBuff;
 
 
     inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]);
     inc(CurrBuff,FFieldBufPositions[Field.FieldNo-1]);
@@ -597,10 +610,17 @@ begin
       end
       end
     else
     else
       SetFieldIsNull(NullMask,Field.FieldNo-1);
       SetFieldIsNull(NullMask,Field.FieldNo-1);
-      
-    if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
-      DataEvent(deFieldChange, Ptrint(Field));
+    end
+  else
+    begin
+    Inc(CurrBuff, GetRecordSize + Field.Offset);
+    Boolean(CurrBuff^) := Buffer <> nil;
+    inc(CurrBuff);
+    if assigned(Buffer) then
+      Move(Buffer^, CurrBuff^, Field.Datasize);
     end;
     end;
+  if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
+    DataEvent(deFieldChange, Ptrint(Field));
 end;
 end;
 
 
 procedure TBufDataset.InternalDelete;
 procedure TBufDataset.InternalDelete;

+ 2 - 1
fcl/db/dataset.inc

@@ -176,7 +176,8 @@ end;
 Procedure TDataset.ClearCalcFields(Buffer: PChar);
 Procedure TDataset.ClearCalcFields(Buffer: PChar);
 
 
 begin
 begin
-  //!! To be implemented
+  if FCalcFieldsSize > 0 then
+    FillByte((Buffer+RecordSize)^,FCalcFieldsSize,0);
 end;
 end;
 
 
 Procedure TDataset.CloseBlob(Field: TField);
 Procedure TDataset.CloseBlob(Field: TField);

+ 57 - 0
fcl/dbtests/testdbbasics.pas

@@ -17,6 +17,7 @@ type
   TTestDBBasics = class(TTestCase)
   TTestDBBasics = class(TTestCase)
   private
   private
     procedure TestfieldDefinition(AFieldType : TFieldType;ADatasize : integer;var ADS : TDataset; var AFld: TField);
     procedure TestfieldDefinition(AFieldType : TFieldType;ADatasize : integer;var ADS : TDataset; var AFld: TField);
+    procedure TestcalculatedField_OnCalcfields(DataSet: TDataSet);
   protected
   protected
     procedure SetUp; override;
     procedure SetUp; override;
     procedure TearDown; override;
     procedure TearDown; override;
@@ -37,6 +38,7 @@ type
     procedure TestEofAfterFirst;           //bug 7211
     procedure TestEofAfterFirst;           //bug 7211
     procedure TestBufDatasetCancelUpdates1;
     procedure TestBufDatasetCancelUpdates1;
     procedure TestDoubleClose;
     procedure TestDoubleClose;
+    procedure TestCalculatedField;
     procedure TestAssignFieldftString;
     procedure TestAssignFieldftString;
     procedure TestAssignFieldftFixedChar;
     procedure TestAssignFieldftFixedChar;
     procedure TestSelectQueryBasics;
     procedure TestSelectQueryBasics;
@@ -423,6 +425,61 @@ begin
   DBConnector.StopTest;
   DBConnector.StopTest;
 end;
 end;
 
 
+procedure TTestDBBasics.TestcalculatedField_OnCalcfields(DataSet: TDataSet);
+begin
+  case dataset.fieldbyname('ID').asinteger of
+    1 : dataset.fieldbyname('CALCFLD').AsInteger := 5;
+    2 : dataset.fieldbyname('CALCFLD').AsInteger := 70000;
+    3 : dataset.fieldbyname('CALCFLD').Clear;
+    4 : dataset.fieldbyname('CALCFLD').AsInteger := 1234;
+    10 : dataset.fieldbyname('CALCFLD').Clear;
+  else
+    dataset.fieldbyname('CALCFLD').AsInteger := 1;
+  end;
+end;
+
+procedure TTestDBBasics.TestCalculatedField;
+var ds   : TDataset;
+    AFld1, AFld2, AFld3 : Tfield;
+begin
+  ds := DBConnector.GetNDataset(5);
+  with ds do
+    begin
+    AFld1 := TIntegerField.Create(ds);
+    AFld1.FieldName := 'ID';
+    AFld1.DataSet := ds;
+
+    AFld2 := TStringField.Create(ds);
+    AFld2.FieldName := 'NAME';
+    AFld2.DataSet := ds;
+
+    AFld3 := TIntegerField.Create(ds);
+    AFld3.FieldName := 'CALCFLD';
+    AFld3.DataSet := ds;
+    Afld3.FieldKind := fkCalculated;
+
+    AssertEquals(3,FieldCount);
+    ds.OnCalcFields := TestcalculatedField_OnCalcfields;
+    open;
+    AssertEquals(1,FieldByName('ID').asinteger);
+    AssertEquals(5,FieldByName('CALCFLD').asinteger);
+    next;
+    AssertEquals(70000,FieldByName('CALCFLD').asinteger);
+    next;
+    AssertEquals(true,FieldByName('CALCFLD').isnull);
+    next;
+    AssertEquals(1234,FieldByName('CALCFLD').AsInteger);
+    edit;
+    FieldByName('ID').AsInteger := 10;
+    post;
+    AssertEquals(true,FieldByName('CALCFLD').isnull);
+    close;
+    AFld1.Free;
+    AFld2.Free;
+    AFld3.Free;
+    end;
+end;
+
 procedure TTestDBBasics.TestEofAfterFirst;
 procedure TTestDBBasics.TestEofAfterFirst;
 begin
 begin
   with DBConnector.GetNDataset(0) do
   with DBConnector.GetNDataset(0) do