1. create table where are some blob and non-blob fields
2. open table with the table component, let say table is named 'Usedtablename'
3. call on the connection the statement 'delete from Usedtablename'
4. call on the component the function 'refresh'
5. call on the component the function append or insert
6. define the field values
7. call post
8. the exception from the subject appears.
The error is in the unit DBAccess, in the method TCustomDADataSet.GetCurrentKeys. The part in the section where keyFieldCount = 0 is wrong, there should be performed a local modification of the field list (to throw away of the blob and object fields), but it modifies the whole field definition cache... We have fixed it by following code:
Code: Select all
procedure TCustomDADataSet.GetCurrentKeys(out KeyFields: TFieldArray; out Values: variant);
var
KeyFieldDescs, DataFieldDescs
(* start of modifications for the fix *)
, LoadedDataFieldDescs
(* end of modifications for the fix *)
: TFieldDescArray;
KeyFieldsCount, DataFieldsCount: integer;
i, j: integer;
RecBuf: TRecordBuffer;
TmpVar: variant;
Delta: integer;
EmptyRecBuf: boolean;
begin
DataFieldDescs := nil;
Assert(FDataSetService <> nil);
FDataSetService.GetKeyFieldDescs(KeyFieldDescs);
KeyFieldsCount := Length(KeyFieldDescs);
SetLength(KeyFields, KeyFieldsCount);
Values := Unassigned;
EmptyRecBuf := not GetActiveRecBuf(RecBuf);
if KeyFieldsCount = 1 then begin
KeyFields[0] := GetField(KeyFieldDescs[0]);
if not EmptyRecBuf then
Data.GetFieldAsVariant(KeyFieldDescs[0].FieldNo, RecBuf, Values);
end
else
if KeyFieldsCount > 1 then begin
Values := VarArrayCreate([0, KeyFieldsCount - 1], varVariant);
for i := 0 to KeyFieldsCount - 1 do begin
KeyFields[i] := GetField(KeyFieldDescs[i]);
Values[i] := Unassigned;
if not EmptyRecBuf then begin
Data.GetFieldAsVariant(KeyFieldDescs[i].FieldNo, RecBuf, TmpVar);
Values[i] := TmpVar;
end;
end;
end
else begin
(* Start of modifications for fix *)
FDataSetService.GetDataFieldDescs(LoadedDataFieldDescs);
DataFieldsCount := Length(LoadedDataFieldDescs);
(* The dataFieldDesc array was originally returned only
* as a pointer to the global storage
* That's why the modification of the array bellow caused problems ...
* The obtained array is copied before modifying the array content now
*)
SetLength(DataFieldDescs, DataFieldsCount);
for I := 0 to DataFieldsCount - 1 do begin
DataFieldDescs[i] := LoadedDataFieldDescs[i];
end;
(* End of modification for fix *)
if DataFieldsCount > 0 then begin
Delta := 0;
Assert(FDataSetService.FSQLGenerator <> nil);
for i := DataFieldsCount - 1 downto 0 do
if FDataSetService.FSQLGenerator.IsBlobDataType(DataFieldDescs[i].DataType) or
FDataSetService.FSQLGenerator.IsObjectDataType(DataFieldDescs[i].DataType) //TODO:
then begin
Inc(Delta);
for j := i to DataFieldsCount - Delta - 1 do
DataFieldDescs[j] := DataFieldDescs[j + 1];
end;
SetLength(KeyFields, DataFieldsCount - Delta);
Values := VarArrayCreate([0, DataFieldsCount - Delta - 1], varVariant);
for i := 0 to DataFieldsCount - Delta - 1 do begin
KeyFields[i] := GetField(DataFieldDescs[i]);
{$IFNDEF CLR}
Values[i] := Unassigned;
{$ENDIF}
if not EmptyRecBuf then begin
Data.GetFieldAsVariant(DataFieldDescs[i].FieldNo, RecBuf, TmpVar);
Values[i] := TmpVar;
end;
end;
end;
end;
end;