Page 1 of 1

Error on error!

Posted: 15.01.2007, 19:50
by gto
Hello there :)

Working on a project with zeos this week, I found a query that has a TField inherited from an old SQL statement and that is not into actual SQL. Means: A defined Field that does not exist:

Into query: Code and Name
Result from SQL: only Code

A normal behaviour from BDE, in runtime or designtime, is to display a message: Field "Name" not found.

Zeos does this, but only in designtime. In runtime I get:

Invalid argument for format '%s'

or in portuguese:

Formato inválido para o argumento '%s'

I know that this message comes from an attempt to use the function Format using the %s format (for string) without providing a string to use. Test case:

Code: Select all

// no error
ShowMessage(Format('The param is: %s', ['test parameter']));

//with erorr
ShowMessage(Format('The param is: %s', []));
Debuging Zeos I found the procedure that raises the error: TDataset.BindFields called from TZAbstractRODataset.InternalOpen.
TDataset.BindFields is defined in delphi 7 at DB.pas, as follows:

Code: Select all

procedure TDataSet.BindFields(Binding: Boolean);
const
  CalcFieldTypes = [ftString, ftSmallint, ftInteger, ftWord, ftBoolean,
    ftFloat, ftCurrency, ftBCD, ftFMTBcd, ftDate, ftTime, ftDateTime,
    ftTimeStamp, ftVariant, ftLargeInt, ftWideString];

  procedure DoBindFields(Fields: TFields);
  var
    I, FieldIndex: Integer;
    FieldDef: TFieldDef;
  begin
    for I := 0 to Fields.Count - 1 do
    with Fields[I] do
    begin
      if Binding then
      begin
        if FieldKind in [fkCalculated, fkLookup] then
        begin
          if not (DataType in CalcFieldTypes) then
            DatabaseErrorFmt(SInvalidCalcType, [DisplayName], Self);
          FFieldNo := -1;
          FOffset := FCalcFieldsSize;
          Inc(FCalcFieldsSize, DataSize + 1);
        end else
        if FieldKind = fkAggregate then
          FFieldNo := -1
        else
        begin
          FieldDef := nil;
          FieldIndex := FieldDefList.IndexOf(FullName);
          if FieldIndex <> -1 then
            FieldDef := FieldDefList[FieldIndex] else
            DatabaseErrorFmt(SFieldNotFound, [DisplayName], Self);
          if FieldKind = fkInternalCalc then
            FFieldNo := FieldDef.FieldNo else
            FFieldNo := FieldIndex + FFieldNoOfs;
          CheckFieldCompatibility(Fields[I], FieldDef);
          if FieldDef.InternalCalcField then
            FInternalCalcFields := True;
          if IsBlob then
          begin
            FSize := FieldDef.Size;
            FOffset := FBlobFieldCount;
            Inc(FBlobFieldCount);
          end;
        end;
        Bind(True);
      end else
      begin
        Bind(False);
        FFieldNo := 0;
      end;
      if Fields[I].DataType in [ftADT, ftArray] then
        DoBindFields(TObjectField(Fields[I]).Fields);
    end;
  end;

begin
  FCalcFieldsSize := 0;
  FBlobFieldCount := 0;
  FInternalCalcFields := False;
  DoBindFields(Fields);
end;
As I see, this procedure bind the defined Fields to the statement Fields. And the line that trigger the error is:
DatabaseErrorFmt(SFieldNotFound, [DisplayName], Self);

Anyone with the same problem? Or that know why BindFields can't access DisplayName of TField ? I'm in need of ideas :!:

Thanks in advance =)

Posted: 17.01.2007, 14:12
by gto
Froget it, forget it.. my fault

In my DBConsts.pas (3rd party modified), the constant SFieldNotFound (responsable for this message) has two %s where it should only have one.

Everything works now :D