[fpc-devel] Recent changes to TField.SetData

LacaK lacak at zoznam.sk
Tue Apr 5 19:02:38 CEST 2011


>>> The whole code, which is repeated (and can be put in one place) is:
>>>
>>> if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then
>>> begin
>>>   DatabaseErrorFmt(SNotEditing,[Name],self);
>>>   exit;
>>> end;
>>> if (Field.FieldNo>0) and not (State in [dsSetKey, dsFilter]) then
>>> begin
>>>   if Read     
>>> OnlythenDatabaseErrorFmtSReadOnlyField,[Field.DisplayName],
>>> Self);
>>>   Field.Validate(Buffer);
>>> end;
>>
>> You are right in your dislike.
>>
>> I will create a 'BeforeSetFieldData' in TDataset and put the code in 
>> there,
>> and the same for 'AfterSetFieldData' with the OnChange code.
>>
> OK,
> Then please do not forget commit necessary changes also in other 
> descendants (not only in TCustomBufDataSet but also in TParadox, 
> TMemDataset,  TFixedFormatDataSet,  TDbf) to completelly fix 'missing 
> onvalidate call' problem.
> Thanks
>
I am still thinking about this.
I have other solution, which is relative simple , puts base logic into 
base TField methods (so all TDataSet descendants can benefit from it) 
and does not negatively affect existing TDataSet descendants and does 
not require introduce new methods (BeforeSetFieldData, AfterSetFieldData).
Let's distributes repeating used code as follows:

1. base checks "before" into procedure TField.SetData(Buffer: Pointer; 
NativeFormat : Boolean);

  820 begin
  821   If Not Assigned(FDataset) then
  822     DatabaseErrorFmt(SNoDataset,[FieldName]);

        if not (State in [dsEdit, dsInsert, dsFilter, dsCalcFields]) then //here should be IMO also dsNewValue
          DatabaseErrorFmt(SNotEditing,[FDataSet.Name],FDataSet);

        if ReadOnly and (FieldNo>0) and not (FDataSet.State in [dsSetKey, dsFilter]) then
          DatabaseErrorFmt(SReadOnlyField, [DisplayName], Self);

  829   FDataSet.SetFieldData(Self,Buffer, NativeFormat);
--------------------------------------------------------------------------

2. into procedure TField.Validate(Buffer: Pointer);

  892 begin
        if FDataSet.State in [dsSetKey, dsFilter] then Exit;
  893   If assigned(OnValidate) Then

--------------------------------------------------------------------------

3. "after call" into procedure TDataSet.SetFieldData(Field: TField; Buffer: Pointer);
     begin
       if not (State in [dsCalcFields, dsFilter, dsNewValue]) then
         DataEvent(deFieldChange, Ptrint(Field));
     end;

--------------------------------------------------------------------------

And now all what we must do, is put into method SetFieldData in TDataSet descendants one line:

Field.Validate(Buffer); 

and one line at end:

inherited; //calls "field change" ... this is done by all TDataSet descendants in fcl-db as a last thing


It is only draft, so some detils may be changed ... ;-)
What do you think ?

Laco.




More information about the fpc-devel mailing list