EPUB | CHM | PDF

Ability to specify library name and path

Top Previous Next

Crux of the matter

PostgresDAC uses PostgreSQL client library (libpq.dll) for work. In versions before 2.5.1:

      • the library was loaded immediately at the start of the application (or the IDE);
      • the library name must be 'libpq.dll';
      • loading was affected by Dynamic-Link Library Search Order.

First issue was the reason of incomprehensible errors at the start of applications if system can not find libpq.dll library. And that the most unpleasant many our developers faced with Access Violation errors in rtlXX.bpl packages (where XX corresponds to the IDE version).

Since the library name was a constant one can't use different libraries depending on the task.

And since there was no opportunity to specify exactly path from where library should be loaded there was a big chance to load wrong one.

Beginning from 2.5.1 version:

      • the library may be loaded by developer using LoadPSQLLibrary procedure;
      • the developer may provide custom name (and path) for LoadPSQLLibrary call;
      • if no library loaded then LoadPSQLLibrary call will be executed exactly before any of TPSQLDatabase objects needs connection;
      • the developer may change PSQL_DLL global variable in this way affecting LoadPSQLLibrary behaviour.

In other words developer has two ways to control library loading. He may load it by explicit LoadPSQLLibrary procedure call. Or setting any of TPSQLDatabase objects Connected property to True, then LoadPSQLLibrary will be called implicitly.

Let's see in example how this may be done. We're assuming that we need to load library exactly from "C:\Program Files\PostgreSQL\8.3\bin\libpq.dll".

program Project1;
{$APPTYPE CONSOLE}
uses
  SysUtils, PSQLDbTables, PSQLTypes;
begin
 LoadPSQLLibrary('C:\Program Files\PostgreSQL\8.3\bin\libpq.dll');
 with TPSQLDatabase.Create(nil) do
  try
   DatabaseName := 'Test';
   UserName := 'vasya';
   UserPassword := 'mnogosala';
   WriteLn(SelectStringDef('SELECT version()', 'unknown'));
  finally
   Free;
  end;
  ReadLn;
end.

In the second example we will use PSQL_DLL global variable and implicit library loading:

program Project1;
{$APPTYPE CONSOLE}
uses
  SysUtils, PSQLDbTables, PSQLTypes;
begin
 PSQL_DLL := 'C:\Program Files\PostgreSQL\8.3\bin\libpq.dll';
 with TPSQLDatabase.Create(nil) do
  try
   DatabaseName := 'Test';
   UserName := 'vasya';
   UserPassword := 'mnogosala';
   WriteLn(SelectStringDef('SELECT version()', 'unknown'));
  finally
   Free;
  end;
  ReadLn;
end.

Hot switching?

It would be kinda natural assumption that there is UnloadPSQLLibrary procedure. Yes, this would be the right one. Hence we may "switch" libraries on the fly. But heaven retribution will find everybody who does not disconnect every TPSQLDatabase object before hot switching:

procedure HotSwitch(const ALibPath: string);
var I: integer;
begin
 for I := 0 to DBList.Count - 1 do
   TPSQLDatabase(DBList[I]).Close;
 UnloadPSQLLibrary;
 LoadPSQLLibrary(ALibPath);
end;

Here DBList is the global variable from PSQLDbTables.pas unit.

If you want to know exactly path from where library is loaded examine result of this function call

S := GetModuleName(SQLLibraryHandle);