Page 1 of 1

[V6] Set TField.Index causes TVirtualTable.Reload+Exception

Posted: Tue 07 Jul 2009 12:49
by cis-wurzen
I am currently using ODAC 5.80 for my app. I recently created a branch for the migration to Delphi 2009 and use ODAC 6.80 in that branch.

One piece of code in the app creates a TVirtualTable in code. With ODAC 6 I get a EConvertError exception ("0.0 is not a valid timestamp") when I try to order the fields of the TVirtualTable (stored user field order). The error is not related to Delphi 2009, because it occurs with Delphi 5 too.

The following test case shows the problem and I see this call stack with Delphi 2009 for it:

:7c812afb kernel32.RaiseException + 0x52
:00451418 ValidateTimeStamp + $64
:00451499 TimeStampToDateTime + $D
:00456e7a TData.PutFieldData + $DA
:004570a4 TData.PutField + $A8
:00466746 TMemDataSet.SetFieldData + $126
:00446143 TDataSet.SetFieldData + $4B
:00466960 TMemDataSet.SetFieldData + $3C
:0043b2c9 TField.SetData + $89
:0043c3b7 TStringField.SetAsAnsiString + $C3
:00470e9a TVirtualTable.LoadFromStream + $5DA
:0046e36a TVirtualTable.Reload + $86
:0046e4bb TVirtualTable.DataEvent + $73
:00439905 TFields.Changed + $1D

Code: Select all

program VTFieldIndexTest;

{$APPTYPE CONSOLE}

uses
  DB, VirtualTable;

function CreateStringField(ADataset: TDataSet; AFieldName: string): TStringField;
begin
  Result := TStringField.Create(ADataset);
  with Result do
  begin
    FieldName := AFieldName;
    DataSet := ADataset;
  end;
  {$IFDEF FIXME}
  ADataset.FieldDefs.Add(AFieldName, ftString);
  {$ENDIF FIXME}
end;

function CreateDateTimeField(ADataset: TDataSet; AFieldName: string): TDateTimeField;
begin
  Result := TDateTimeField.Create(ADataset);
  with Result do
  begin
    FieldName := AFieldName;
    DataSet := ADataset;
  end;
  {$IFDEF FIXME}
  ADataset.FieldDefs.Add(AFieldName, ftDateTime);
  {$ENDIF FIXME}  
end;

var
  vt: TVirtualTable;
begin
  vt := TVirtualTable.Create(nil);
  try
    CreateStringField(vt, 'STRING');
    CreateDateTimeField(vt, 'DATETIME');

    vt.Open;

    vt.Append;
    vt.Fields[0].AsString := 'A';
    vt.Fields[1].AsDateTime := 0;
    vt.Post;

    vt.Fields[0].Index := 1;
  finally
    vt.Free;
  end;
end.

Posted: Wed 08 Jul 2009 08:05
by Plash
You can fix this problem by setting the VTOldBehavior global variable from the VirtualTable unit to True.

Note: it is recommended to create FieldDefs for VirtualTable. In this case TField objects will be created automatically using FieldDefs. FieldDefs hold internal data structure for VirtualTable and are not changed when you change the Index property of TField.