Search code examples
delphifiredacdelphi-10.1-berlin

How can I find the MS Access version and/or dll name used for a FireDac connection?


I have a FireDac connection to an Microsoft Access database. I'm configuring the Parms on the connection like so:

Connection.Params.Add('DriverID=MSAcc');
Connection.Params.Add('Database=' + FDatabasePath);
Connection.Connected := true;

Generally this works great. However, in some cases an old MS Access driver installed. We would like to detect that situation and alert the user so they can install a new driver.

How can I get the driver version, or at least the VendorLib name, that FireDac found and used to make the connection?

I know I can specify a VendorLib on a Phys Connection Link prior the opening my connection. I don't want to do that. I want FireDac to go through it's process to find and use the most relevant driver on the system. However, once that is done I would like to know what driver it ended up using.

I tried creating a TFDPhysMSAccessDriverLink after the connection was open hoping that the ActualDriverId or VendorLib properties would be set. But ActualDriverId is MsAcc and VendorLib is blank.


Solution

  • 1. Get version of the driver

    You can get the driver version in ordinal form by the DriverVersion property, or as a string (which can include also driver description) by the DRIVER_VER property. The queried SQL_DRIVER_VER info type is in ODBC API described like:

    SQL_DRIVER_VER (ODBC 1.0)

    A character string with the version of the driver and optionally, a description of the driver. At a minimum, the version is of the form ##.##.####, where the first two digits are the major version, the next two digits are the minor version, and the last four digits are the release version.

    With FireDAC you can get it this way:

    uses
      FireDAC.Phys.ODBCWrapper;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      DriverVerStr: string;
      DriverVerInt: TFDVersion;
      ODBCConnection: TODBCConnection;
    begin
      ODBCConnection := TObject(FDConnection.CliObj) as TODBCConnection;
    
      DriverVerStr := ODBCConnection.DRIVER_VER;
      DriverVerInt := ODBCConnection.DriverVersion;
    
      Memo.Lines.Add(Format('DriverVerStr: %s', [DriverVerStr]));
      Memo.Lines.Add(Format('DriverVerInt: %d', [DriverVerInt]));
    end;
    

    2. Get version of ODBC that the driver supports

    To get ODBC version supported by the used driver you can use the DriverODBCVersion property to obtain ordinal value, or DRIVER_ODBC_VER to get a string value. Queried SQL_DRIVER_ODBC_VER data type info is described like:

    SQL_DRIVER_ODBC_VER (ODBC 2.0)

    A character string with the version of ODBC that the driver supports. The version is of the form ##.##, where the first two digits are the major version and the next two digits are the minor version. SQL_SPEC_MAJOR and SQL_SPEC_MINOR define the major and minor version numbers. For the version of ODBC described in this manual, these are 3 and 0, and the driver should return "03.00".

    With FireDAC you can get it this way:

    uses
      FireDAC.Phys.ODBCWrapper;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      ODBCVerStr: string;
      ODBCVerInt: TFDVersion;
      ODBCConnection: TODBCConnection;
    begin
      ODBCConnection := TObject(FDConnection.CliObj) as TODBCConnection;
    
      ODBCVerStr := ODBCConnection.DRIVER_ODBC_VER;
      ODBCVerInt := ODBCConnection.DriverODBCVersion;
    
      Memo.Lines.Add(Format('ODBCVerStr: %s', [ODBCVerStr]));
      Memo.Lines.Add(Format('ODBCVerInt: %d', [ODBCVerInt]));
    end;
    

    3. Get version of the DBMS product accessed by the driver

    You can get the accessed DBMS product version by the DBMS_VER property. ODBC API describes the queried SQL_DBMS_VER info type as:

    SQL_DBMS_VER (ODBC 1.0)

    A character string that indicates the version of the DBMS product accessed by the driver. The version is of the form ##.##.####, where the first two digits are the major version, the next two digits are the minor version, and the last four digits are the release version. The driver must render the DBMS product version in this form but can also append the DBMS product-specific version. For example, "04.01.0000 Rdb 4.1".

    With FireDAC you can get it this way (there is no property returning parsed ordinal version number, so let's try parsing to ordinal value by ourselves):

    uses
      FireDAC.Stan.Util, FireDAC.Phys.ODBCWrapper;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      DBMSVerStr: string;
      DBMSVerInt: TFDVersion;
      ODBCConnection: TODBCConnection;
    begin
      ODBCConnection := TObject(FDConnection.CliObj) as TODBCConnection;
    
      DBMSVerStr := ODBCConnection.DBMS_VER;
      DBMSVerInt := FDVerStr2Int(DBMSVerStr);
    
      Memo.Lines.Add(Format('DBMSVerStr: %s', [DBMSVerStr]));
      Memo.Lines.Add(Format('DBMSVerInt: %d', [DBMSVerInt]));
    end;
    

    4. Get FireDAC unified version information

    FireDAC provides the ClientVersion and ServerVersion properties which are accessible through the ConnectionMetaDataIntf interface property of the connection object.

    For ODBC drivers the ClientVersion property returns the driver version (described in section 1 here) if the driver is not a single tier driver, DBMS product version otherwise (described in section 3). The ServerVersion returns always DBMS product version (described in section 3 here) for ODBC drivers.

    For example:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Metadata: IFDPhysConnectionMetadata;
    begin
      Metadata := FDConnection.ConnectionMetaDataIntf;
      try
        Memo.Lines.Add(Format('ClientVersion: %d', [Metadata.ClientVersion]));
        Memo.Lines.Add(Format('ServerVersion: %d', [Metadata.ServerVersion]));
      finally
        Metadata := nil;
      end;
    end;