Resolving size mismatch exceptions with the Delphi 7.1 update

By: John Kaster

Abstract: If you are getting size mismatch exceptions in Delphi 7 applications after applying the Delphi 7.1 patch, read this article.

Size mismatch exceptions

QualityCentral Report# 3974 describes a data corruption issue that can occur in Delphi from versions 5 to 7.0. The Delphi 7.1 update fixes this bug by generating an exception when the persistent version of a TStringField object (the field definition you might store in your DFM file) is larger than the size of the database column it references.

This exception also gets raised in the XMLMapper tool that ships with Delphi 7.

For example, if a persistent field definition has a Size property value of 20, but the column in the database is only 15 characters, a "Size mismatch" exception will be generated at runtime. It will look something like this:

ClientDataSet1: Size mismatch for field 'CONTACT_FIRST', expecting: 20 actual: 15.

This is not an error the Delphi compiler will catch. It is only detectable at runtime and design time. If you maintain good practices and update your persistent field definitions when your database schema changes, you will not encounter this error.

Your options for using this patch

If you are encountering this error, you have some options for the best way to address it.

Update your persistent fields in the application

In the Delphi IDE, if you open a form or datamodule that contains datasets that are active at design time, you will get an exception detailing the size mismatch.

Detecting these errors could be a time consuming process. If you have many datasets or forms in your application, you can use this routine in your form or datamodule's OnCreate event to get a list of database exceptions that occur when the tables are opened:

procedure <MyForm>.CheckFieldSizes;
var
  i: integer;
  d: DataSet;
  errors: string;

begin
  for i := 0 to ComponentCount - 1 do
    if Components[i] is TDataSet then
    begin
      d := TDataSet(Components[i]);
      if not d.Active then
      begin
        try
          try
            d.Active := True; // Verify data field size
          except
            on E: EDatabaseError do
              errors := #13 + E.Message;
          end;
        finally
          d.Active := False;
        end;
      end;
    end;
  if errors <> '' then
    ShowMessage(Name + ' has these Dataset errors:' + errors);
end;

Instead of calling ShowMessage, you may want to write the list of errors out to a text file or email them.

If you find any errors, here are some options for correcting the persistent field data size properties:

  • You can select the Dataset object that has size mismatches between the persistent object and the data columns, double click on it to bring up the persistent field editor, and correct the Size property for the field.
  • If you're not sure of the correct data size, remove the erroneous field definition, and add it back.
  • If there is more than one conflicting field definition, you may want to remove all persistent fields from the dataset, and add all of them back at once

Roll back the fix

For applications where is it determined that the circumstances surrounding the size mismatch are acceptable, you may choose to revert the changes to the database runtime files instead of correcting the size mismatches in the application.

The following table lists the files to copy from your original Delphi 7 CD if you wish to revert back to the version that originally shipped with Delphi 7. In this table, [Delphi 7] should be replaced with your Delphi 7 installation directory location.

File on CDDestination on disk
\Install\System32\dbrtl70.bpl[boot drive]\Windows\System32
\Install\Program Files\Borland\Delphi7\Lib\DB.dcu[Delphi 7]\Lib
\Install\Program Files\Borland\Delphi7\Lib\Debug\DB.dcu [Delphi 7]\Lib\Debug
\Install\Program Files\Borland\Delphi7\Source\Vcl\DB.pas [Delphi 7]\Source\Vcl

Wait for the patch

You could delay deploying an application that uses the Delphi 7.1 patch until a new version of this fix is available.

I want to mention that the current solution provided in Delphi 7.1 is not actually a bug. It is a correct and appropriate fix for this situation. However, since this size mismatch has been permitted between Delphi 5 and Delphi 7.0, the potential of raising exceptions in applications that previously ran fine is quite large. Borland feels the potential is too large to allow the fix to remain as it is currently implemented, since the effort on the part of our customers to modify their applications to conform to the newly enforced data integrity rules could be so significant.

What is the correct fix?

Borland is currently making an additional source code change that will enforce data integrity without raising an exception, and we will make that updated version available as soon as possible.

These were the options we evaluated before proceeding with the new fix:

  1. Roll back the change to the Delphi 7.0 version that allowed for memory corruption. Verdict: No, we do not want to leave code in place that could result in data corruption.
  2. Relax the size mismatch constraint on read-only fields, because a size mismatch for those fields cannot cause memory corruption. Verdict: Yes, implement this change.
  3. At runtime, when loading of the field objects from the database metadata, ensure that persistent field object sizes are not larger than the actual data column size. Verdict: Yes, implement this change.

When can I get the new fix?

These are the steps that will occur before the patch is officially released:

  1. R&D will modify the code and write unit tests to verify the fix
  2. QA will run a quick "smoke test" on it to verify that the fix appears solve the problem
  3. On BDN, we will:
    • Post a public beta of the dbrtl70.bpl package to CodeCentral
    • Create a public beta area in QualityCentral to track issues with the fix
    • Post an article on BDN announcing the public beta, and describing its purpose
  4. While the public beta is proceeding, QA will run our complete database test suite on at least one database driver, which will take 4 days
  5. If the fix works as expected, we will then certify a new patch and make it available for registered users to download. This patch should support updating both the original Delphi 7 install and the 7.1 patch.

Server Response from: ETNASC01