pgExpress Driver 4.50

Steve Howe

All rights reserved. Built at: Tue Mar 27 13:57:49 2012


IMPORTANT!!!! - About this documentation
1. Introduction
1. Introduction
2. History
3. Features and Highlights
4. Distributions
5. Demos
2. Using the pgExpress Driver
1. Requirements
1.1. Libpq
2. Installation
2.1. dbExpress 4.0 (Delphi 2007+) support
3. Protocols
4. Types Mappping
5. Customizing the pgExpress Driver
5.1. Driver Parameters
5.2. Special Params
5.3. Custom Info
6. Advanced Features
6.1. Stored Procedures Support
6.2. Fetch Cursors
6.3. Authentication
6.4. Automatic numeric format detection
6.5. Native Int8 support
6.6. Retaining Cursors
6.7. BLOBs Support
6.8. SSL Support
6.9. NOTICEs support
6.10. Asynchrounous connections
6.11. Canceling a query
3. Localization
1. Multibyte, UNICODE and Locales
2. Multilanguage Driver
3. Translating the pgExpress Driver
4. PGEDriverUtils.pas
GetPGVersion
GetTTY
GetBackendPID
GetOnline
GetRetainCursor
SetRetainCursor
GetLanguage
SetLanguage
CancelQuery
5. Ordering and Licensing
1. Ordering
2. Restrictions of the Demo driver
3. License Agreement
3.1. Demo Version Restrictions
3.2. Disclaimer
6. Notes
1. Known Issues
2. Notes
3. Development tips
4. Version-specific Notes
7. About the pgExpress Driver
1. Credits
2. Contact, Support, Bugs
A. FAQ and Changelog
1. F.A.Q.
2. Changelog

IMPORTANT!!!! - About this documentation

This documentation is the guide for using the pgExpress Driver. Of course some questions can arise and we are at your disposal for solving them; just write as at support@vitavoom.com.

When possible, please try to refer to the online documentation since it will always be the most up to date reference available (more then the version released with the driver distribution).

Note

There are currently three formats of this documentation:
  • HTML - one chunk: a single, large html file containing all documentation.
  • HTML - chunked: html format, split in several files. Default for the packed (.zip) versions of the pgExpress Driver
  • HTMLHelp: Microsoft HtmlHelp (.chm) format. This is the default for the installable (.exe) versions of the pgExpress Driver.

If you want another documentation format, please just go to the downloads area of our site.

Chapter 1. Introduction

1. Introduction

The pgExpress Driver is a PostgreSQL v7.1+ dbExpress Driver for Codegear Delphi 6+/Codegear Kylix/Codegear C++ Builder 6+.

It can use all PostgreSQL field types, and is compliant to the Codegear specifications of dbExpress drivers.

Please refer to the Changelog of the pgExpress Driver for the changes history.

2. History

The Vita Voom SoftwarepgExpress Driver born out of the lack of good PostgreSQL support for the Delphi community. Mr., Steve Howe , pgExpress Driver's author, have also worked on the Zeos Library project for a couple months, but quit from it since he couldn't agree with many of the development directives.

The pgExpress Driver was developed months earlier then Codegear's PostgreSQL Driver for Kylix, and at the time it was developed, it was the first driver in the world written using Delphi. We released the first pgExpress Driver beta in July 05, 2001.

Since then, Vita Voom Software™ have stablished itself as a leading PostgreSQL access provider for the Delphi community.

3. Features and Highlights

The pgExpress PostgreSQL dbExpress driver can access PostgreSQL databases, use all its field types, and is complient to the Codegear specifications of dbExpress drivers. The pgExpress Driver also includes support for stored procedures, through use of PostgreSQL functions.

Arrays are mapped as strings (see Known Issues) and ADT (custom fields) support will be fully supported only by the pgExpress Suite. It has support for all the most commonly used PostgreSQL field types; notably: int2, int4, int8, serial, char, varchar, text, date, datetime, time, timestamp, timestamp with time zone, BLOB (large objects; read only), float, real, numeric and others).

Highlights of the pgExpress Driver:

  • 100% VCL/CLX implementation - unlike other drivers which are coded in C language, our driver is 100% coded using Codegear Delphi itself (and Codegear Kylix). This automatically makes it portable to any platform where Delphi/Kylix/C++ Builder are available.
  • Portability: Delphi, Kylix and C++ Builder are supported.
  • dbExpress protocol 3.0 support; pgExpress is the first driver to implement it outside Codegear.
  • FAST: The pgExpress Driver is highly optimized, and designed to minimize the traffic to the server as much as possible.
  • Low Cost: pgExpress has NO RUNTIME FEES and does not need to be licensed in a per machine basis. PostgreSQL itself has the one of the most unobstrusive licenses in the market - BSD (totally free).
  • Exclusive features: the Vita Voom SoftwarepgExpress Driver has much more features then the Borland's Kylix PostgreSQL driver, is available also for Delphi and has features not found on any other driver. Some of the exclusive pgExpress features (over Codegear's PostgreSQL driver) are:

    • Delphi6/7/8/2005/2006/2007 support
    • Codegear C++ Buildersupport
    • Kylix1/2/ 3 support
    • Supported databases:
    • Extensive documentation
    • Full types support - all regular types from PostgreSQL are supported (see Known Issues).
    • Automatic support for locale/decimal separator settings
    • Multibyte support
    • Connection timeout Support
    • Several custom settings that modify the way the driver works.
    • Stored Procedures Support (emulated through functions)
    • Automatic Fetch Cursors
    • Native support for LargeInt/Int8/Int64types
    • Support for unknown types
    • Hability to work with quoted object names
    • Schema support (for PostgreSQLv7.3+)
    • Custom, elucidating error messages
    • Asynchronous connections, with option to Cancel them (exclusive among all Delphi interfaces).
    • UNICODE (TWideString) support.
    • Localization. You can easily have driver messages in your own language; check the languages already implemented, or implement yours.
    • Support - Vita Voom Software™ primes for its custumers. We have a real great and responsive support system for ensuring our customers have the best and fastest possible support.

Other advantages:

  • Reability - Since the driver is based on dbExpress implementation, it minimizes the possibility of bugs on database applications, because many of the code that actually access the databases from Delphi it is proven technology written by Codegear.
  • Database independence - you can switch to another database, just by replacing the driver for another one. This is a main advantage of the dbExpress technology itself.
  • Small - The pgExpress Driver is around 100Kb (non-Multilanguage version).

4. Distributions

The pgExpress Driver is distributed primarily thorugh our website at http://www.vitavoom.com.

There are a few options available for downloading:

Version Description
About the licensing:
Demo Demonstration (trial) version.  
Full Full version, with all features. Registered users only.  
About the localization:
Inside the distribution, there are two versions of the driver: a default one, and a Multilanguage Driver:
Language Delphi Kylix
Default (english) dbexpge.dll libdbexppge.so
Multilanguage dbexpge_ml.dll libdbexppge_ml.so
About the packaging:
Zip Version that is packaged with the Zip packer. It has a (.zip extension)  
Installable Version which comes in a installer (.exe extension). Windows only.  

These versions are combined into distributions. Examples:

  • Demo, Multilanguage, Installable version - pgeDriver-full-4.00.exe
  • Demo, Zip version - pgeDriver-4.00.zip

5. Demos

For your convenience, we have included a few demos in the Demo directory on the pgExpress Driver distribution:

  • PGEDemo - covers the basis of connecting to a PostgreSQL database. VCL and CLX versions available.
  • Params - uses Params to make a search on a PostgreSQL database table.
  • Sequences - demonstrates use of sequences or any other server-generated values (VCL-only).
  • Console - demonstrates how to use pgExpress from a console mode application.
  • StoredProcs - demonstrates how to use Stored Procedures (PostgreSQL Functions) with pgExpress.

For more information on each demo, please refer to the readme.txt file inside each demos's directory.

Note

These demos try to connect to a named connection, from the dbxconnections(.ini) file, called PGEConnection. If you don't have such a named connection, please create one.

Chapter 2. Using the pgExpress Driver

1. Requirements

The basic requirements for using teh pgExpress Driver are:

  • Delphi 6+, Kylix, or Codegear C++ Builder 6+;, with dbExpress
  • A libpq library compatible with the server version the driver will connect.
  • A compatible PostgreSQL server version 7.1 or newer should work fine, but we recommend using at least version 7.4, or preferably, the latest one.

1.1. Libpq

The pgExpress package contains a libpq library that can be used to connect to your database server. It is supplied just to make installation easier; however, you can use any libpq as long as it is compatible with your database server.

It is possible that the supplied libpq library contains some dependencies that are not met by your system, or by the deployment system. In that case, we suggest to either compile the libpq yourself.

Under Windows, you can either use our supplied libpq, which should work on all related platforms out of the box, or get the binary from the PostgreSQL distribution. The supplied libpq does not include SSL support in order to make requirements easier to achieve.

We look forward to include always the latest libpq version in the pgExpress package, but feel free to replace it with the latest version you have on your system at any time. For Windows users, please refer to PostgreSQL for Windows distribution, and get the latest "no-installer" distribution, such as "postgresql-8.1.2-1-binaries-no-installer.zip". This file will contain the latest libpq library compiled for Windows, and any additional requirements.

The dependencies for the libpq.so library can vary from version to version, but at the time of this writing, are:

libpq.so.4:
libssl.so.4 = /usr/lib/libssl.so.4 (0x28176000)
libcrypto.so.4 = /lib/libcrypto.so.4 (0x281a4000)
libcrypt.so.3 = /lib/libcrypt.so.3 (0x28296000)

Note for libpq incompatibilities:

There could be some incompatibility problems between the libpq.dll /libpq.so library provided in the distribution and other clients such as psql - specialy under Linux/Kylix. To solve this, you can either:

If you rename the library to libpq_pge.so, for instance, your entry should become VendorLib=libpq_pge.so accordingly. There are more instructions on the dbxdrivers.ini/dbxdrivers file below.

  1. (for Linux only)- use the standard libpq.so file from the original PostgreSQL distribution, as it is, on your system;
  2. Rename the libpq.so/libpq.dll file from the pgExpress Driver distribution to something else, and update the entry on the dbxdrivers.ini /dbxdrivers file (which is by default
    VendorLib=libpq.so
    
    under Kylix or
    VendorLib=libpq.dll
    
    under Windows.

2. Installation

The pgExpress Driver PostgreSQL dbExpress Driver installation procedure is similar to any other dbExpress driver's installation.

If you want to install the Delphi version, the files are under the pgExpress installation's Delphi directory; for the Kylix files, the directory is Kylix'.

If you're using the installer version (*.exe), it can perform the operations below for you, except configuring your connections parameters (what you can do manually by editing that file or just double-clicking a TSQLConnection component). You can edit the default [PGEConnection] entry it creates. The steps for manual installation are:

  1. Copy the driver dbexppge.dll (libdbexppge.so on Linux/Kylix) to a folder in your path. If you are using the multilanguage and/or protocol 3.0 driver, the driver name on the package will be another, such as dbexpge30-ml.dll or libdbexppge.so. It's your choice to rename the file or use the corresponding name on the entry on the dbxconnections(.ini) file. The usual folder is $Delphi\bin on Windows (where $Delphi is the Delphi's installed folder), or $kylix/bin on Kylix, but as long as it's on your path, you can choose any other folder.
  2. Copy the libpq.dll (libpq.so on Linux) file to a dir on your PATH. Please try to use the libpq supplied with the distribution. If you're under Linux, the standard libpq.so from the PostgreSQL original installation should work. Check also Section 1.1, “Libpq”.
  3. Setup the entries on the dbxdrivers.ini and dbxconnections.ini dbExpress configuration files. These files are usually at the $ProgramFiles\Common Files\Borland Shared\DBExpress folder. The changes to be applied are the following:
  4. Edit the dbxdrivers.ini file. On Kylix, this file is called dbxdrivers. On the [Installed Drivers] section, add the PostgreSQL=1 key and value:
    [Installed Drivers]
    DB2=1
    Interbase=1
    MYSQL=1
    Oracle=1
    PostgreSQL=1
    
  5. Still on this file, add the [PostgreSQL] section:
    [Oracle]
    GetDriverFunc=getSQLDriverORACLE
    LibraryName=dbexpora.dll
    VendorLib=OCI.DLL
    BlobSize=-1
    DataBase=Database Name
    ErrorResourceFile=
    LocaleCode=0000
    Password=password
    Oracle TransIsolation=ReadCommited
    User_Name=user
    
    [PostgreSQL]
    GetDriverFunc=getSQLDriverPOSTGRESQL
    LibraryName=dbexppge.dll
    VendorLib=LIBPQ.DLL
    

    Note:

    On Kylix, the PostgreSQL section is slightly different to reflect the Linux library file names:

    [PostgreSQL]
    GetDriverFunc=getSQLDriverPOSTGRESQL
    LibraryName=libdbexppge.so
    VendorLib=libpq.so
    

    Still on Linux/Kylix, you must add your driver's path to the LD_LIBRARY_PATH environment variable (or copy the driver to your Kylix's bin subdirectory):

    LD_LIBRARY_PATH=/home/steve/lib/
    export LD_LIBRARY_PATH
    

    Edit the dbxconnections.ini file. On Kylix, it's is called dbxconnections. This file lists all the dbExpress connections and it can contain as many entries for the pgExpress Driver as you might want add. We supply here an example connection, but you should modify it to meet your own settings (specially the server address, database name, user name and password) params:

    [PGEConnection]
    BlobSize=32
    HostName=host
    Database=database_name
    DriverName=PostgreSQL
    Password=temp123
    User_Name=steve
    

    The only required parameters are Database, DriverName, UserName and Password if desired. You can use a more reduced form like the one below (you're encouraged to use it):

    [PGEConnection]
    DriverName=PostgreSQL
    Database=hostname/database_name
    User_Name=steve
    Password=temp123
    

    The other parameters are optional (only those listed above are supported by the pgExpress Driver) and their meaning is that on dbExpress documentation. Pay special attention to the Database parameter. dbExpress only will load the HostName parameter if you set the TSQLConnection.LoadParamsOnConnect property to True. We at Vita Voom Software™ have used the following rules for the format of the Database parameter that avoid that confusion and also adds support for a Port parameter. It seems like an URL:

    host:port/database
    

    Where:

    • host is the Hostname (DNS or IP) of the machine. If you don't supply this parameter, it defaults to localhost.
    • port is the port to connect to, on the database server host. This do not need to be supplied, if you use the default port (5432). But if you do supply this parameter, you need also specify the host name, and separate the host and port with a colon (':').
    • Database is the database name to connect to. This parameter must be supplied.
    • The following are valid Database parameters:
      Database = myserver.mydomain.com/database
      Database = myserver.mydomain.com:5432/database
      Database = 111.111.111.111:5432/database
      Database = database
      

      Note that if you supply both the HostName and Database parameters with embedded hostname (as show above), the Database parameter will prevail. Don't forget you can add as many sections to the dbxconnections file as you want, like this:

    [PGEConnection]
    DriverName=PostgreSQL
    Database=hostname1/database_name
    User_Name=steve
    Password=temp123
    
    [pgserver]
    DriverName=PostgreSQL
    Database=pgserver/database_name
    User_Name=john
    

That's it; the driver should be working now.

Notes:

  • The default location for the dbxdrivers(.ini) and dbxconnections(.ini) files vary from each distribution; for instance, on Kylix it is ~/.borland, on Delphi6 and 7 it is %CommonFiles%\Borland Shared\DBExpress, and on BDS 2006 it is %ProgramFiles%\Borland\BDS\4.0\dbExpress. Please refer to your IDE documentation for the exact location of those configuration files. Also, remember you can distribute them in the same directory your application is located; that should make distribution easier.
  • Inside the distribution there are example dbxdrivers(.ini) and dbxconnections(.ini) for both Delphi and Kylix.

2.1. dbExpress 4.0 (Delphi 2007+) support

The pgExpress Driver for protocol 3.0 is compatible with Delphi 2007+ which uses the version 4.0 of the dbExpress protocol. We are already in late development of a 4.0 version of our driver, but until there the current version of the driver can be used in compatibility mode by following the these instructions:

  • Use the protocol 3.0 driver (dbexppge30.dll)
  • Add the following additional strings to the [PostgreSQL] section of dbxdrivers(.ini):

    [PostgreSQL]
    DriverUnit=DBXDynalink 
    DriverPackageLoader=TDBXDynalinkDriverLoader 
    DriverPackage=DBXCommonDriver110.bpl
    
  • Distribute the DBXCommonDriver110.bpl package with your application.

Upgrading to Delphi 2007+

When upgrading to Delphi 2007+, there are some issues that must be observed:

  • Delphi 2007 do not support TFMTBcdFields; therefore, the pgExpress Driver maps NUMERIC/DECIMAL types as TBcdFields. Historically, a TFMTBcdField had more precision then a TBcdField, so pgExpress used that type in the mapping. If you have fields statically defined as TFMTBcdField, they can produce runtime error messages when the driver returns them as being TBcdField. You'll need to change the static definitions to map the new type; that can be easily done by either removing and readding these fields or doing a search/replace on the .pas and .dfm files that contain "TFmtBcdField"; replace it with "TBcdField".
  • The driver will probably detect by itself it's running under dbExpress4.0, but you can for force it by using the DBX4Compatible special param.
  • There are some issues using the driver in compatibility mode; sometimes libpq.dll errors could be raised. We are working on a native dbExpress4 version that will overcome all issues and fully utilize the new dbExpress architecture.

3. Protocols

With the introduction of BDS 2006, there is a new dbExpress protocol, which is version 3.0. Older protocols are considered to be version 2.5. Protocol 3.0 mainly adds WideString (UNICODE) support, native int8 support and a few new interfaces. Please check Section 1, “Multibyte, UNICODE and Locales” for details.

The pgExpress Driver supports both protocols, in addition to Kylix support, all in one package. Protocol 3.0 drivers, however, will work only with BDS 2006 or later applications; protocol 2.5 drivers should work with any application designed for dbExpress.

The protocol 3.0 drivers have a '30' suffix labeled in their names, such as:

dbexppge30.dll
dbexppge30-ml.dll

You can either rename the "30" files to the traditional "dbexppge.dll file name, or change the dbxconnections(.ini)/TSQLConnection entry to point to the new file name.

The pgExpress Driver is the first third-part dbExpress driver to implement the protocol 3.0 interfaces.

dbExpress 4.0 support

Support for dbExpress 4.0 for Delphi 2007+ is in late development, but we already support that compiler by using the compatibily mode; please check Installation on dbExpress 4.0 protocol (Delphi 2007+).

4. Types Mappping

This is a quick guide to show how the PostgreSQL types are mapped into dbExpress types by the pgExpress Driver:

Table 2.1. 

PostgreSQL pgExpress Obs
int2 TSmallIntField  
int4 TIntegerField  
oid TIntegerField As of pgExpress 4.30, OID fields will always be mapped and int4 to avoid confusion with Large Objects
int8 TLargeIntField/TStringField/TIntField The dbExpress technology does not have native support for 64 bit integers; however, by using a hack, we provide native Int8 support. Please note the TIndexDef issues associated with native Int8 usage in the link here. This mapping is controlled by the Int8Mode Special Param.
char TStringField Fixed length. The same UNICODE/WideChar notes from varchar type apply.
varchar TStringField/TWideString

TStringField.Size will be set to the maximum length. It's not adviced to set a maximum value too long in the table definition to keep the memory requirements low in the dbExpress row buffers. See here for details. If UnicodeAsWideChar is set to True, and the client encoding is UNICODE, the fields will be mapped as TWideStringField.

If you want/need large values, try using the TEXT field type which maps into a BLOB/Memo (TMemoField) field. This field reads up to to 32kb (dbExpress limitation).

varchar fields with no size specifier is identical to a text field and will be mapped in pgExpress just as a text field.

text TBLOBField/Memo Check our FAQ for more info on this. Text fields mapped as Memo will be faster and more efficient in terms of memory. You can also map them as strings (padded at 32Kb due to dbExpress limitation); check here.
xml TBLOBField/Memo See notes for text fields.
numeric TFMTBCDField VCL/CLX TFMTBCDFields support up to 32 digits. If you have a field with more then that, it will get mapped as TStringField.Note: TFMTBCDField is used instead of TBCDField because it allows greater precision.
time TTimeField See note below. The time field type support fractions.
timetz TTimeField Timezones and second fractions aren't supported by VCL/CLX and they can give your trouble when used in a WHERE clause on INSERT/UPDATE/DELETE queries. Please refer to our FAQ for more info.
date TDateField Timezones are not supported by VCL/CLX
timestamp TTimeStampField See note from fractions on the timetz field.
timestamptz TSQLTimeStampField See notes from timezones and fractions on the timetz field.
bool TBooleanField  
name TStringField Fixed length; name is a field type used internally by PostgreSQL.
bpchar TStringField Fixed length.
_bpchar TStringField Fixed length.
oid TIntegerField Integer
float4 TFloatField Actually TFloatField can support more precision and scale then float4 fields and are recommended. You can teorically have a overflow or underflow if someone tries to insert a bad value.
float8 TFloatField  
abstime/reltime TTimeField See note for time fields.
interval/tinterval TStringField Since there is no interval type in VCL, we have to map these types as strings.
bytea TVarBytesField, Blob/Graphic or Blob/binary See ByteaMode Special Param. TVarBytesFieldReads up to 32kb (dbExpress limitation).
money TCurrencyField The money field is obsolete. The PostgreSQL documentation advices to use numeric or float8 fields instead.
lo TBlobField/Binary Following the PostgreSQL ODBC driver convention, the 'lo' field represents Large Objects. Consider using Bytea fields as BLOBs instead.
Other TStringField Unknown fields are mapped by default as Strings. You can turn this off (and thus don't use the fields at all) by toggling the MapUnknownAsString special param.

5. Customizing the pgExpress Driver

5.1. Driver Parameters

This is a list of the standard Driver Parameters supported by the pgExpress Driver (please check your Delphi help on Driver Parameters for more information on each of them).

Table 2.2. Driver Parameters

Parameter Obs.
DriverName  
Database Used also to provide Special Params to the pgExpress Driver. This parameter can also be used as an URL for providing extra host and port info:
host:port/database
Please check the Installation section for more details.
User_Name
Password See also the Authentication section.
BlobSize This parameter is actually ignored, since PostgreSQL can report the exact Blob field size.
LocaleCode See also the Multibyte, UNICODE and Locales section.
RowsetSize Only works if the BlockRead param is True.
HostName Name can instead be specified as a member of the Database paramater.
RoleName Will set a PostgreSQL7.3+ schema (namespace) to log in. Please check here for more details. Multiple Schemas can be specified (just as in PostgreSQL) if separated by collons, such as:
RoleName = public,schema1,schema2
ServerCharset See also Multibyte, UNICODE and Locales.
Custom String This param allows to supply Special Params through a way other then the traditional, i.e. after the Database. D7+ only.
ServerPort

Allows setting the port to connect to. D7+ only.

Can instead be specified as a member of the Database paramater.

ConnectionTimeout The ConnectionTimeoutSpecial Param can be used on Delphi 6/7 too, or Kylix. D7+ only.
BlockingMode If False, asynchronous connections will be used to connect to the server.
Decimal Separator Same as ServerDecimalSeparator, but since BDS 2006, it is also supported as a regular dbExpress parameter. It will not work with applications built with older IDEs.
ConnectionString dbExpress applications (BDS 2006+), support a custom connection string, that will be passed directly to the PQconnectdb() function, and thus supporting anything that function supports. You can use that parameter instead of Database parameter, User_Name parameter, etc. Syntax will be the same as of the conninfo parameter of the PQconnectdb() function.
ErrorResourceFile Allows to set the language resource file for the driver. Please refer to Multilanguage Driver section for more details.

Notes:

The behavior for this parameter has changed on pgExpress v3.0. To get the same behavior as the v2.X series, check the Language.

Trim Char When True, trailing space chars CHAR fields will be trimmed. VCL/CLX default is False.

5.2. Special Params

The pgExpress Driver has a few special parameters that can be used to customize its behaviors; we refer to them as "Special Params". Default values are formatted like this.

IMPORTANT:

To set a special param, add it in your dbxconnections(.ini) file after the database parameter, such as:

          [PGEConnection]
          Database=localhost/template1,TextAsMemo=False,ByteaMode=asVarBytes
          ...
        

Table 2.3. Special Params

Key Values Meaning
TextAsMemo
True
False
If True, the PostgreSQL TEXT fields will be mapped as Blob (Memo); if False (default), it will be mapped as String. A VARCHAR field with no length specifier behaves exactly like a TEXT field.

Obs:

If mapped as string, a TEXT field will be padded at the maximum string length imposed by dbExpress (~32Kb).
NumericAsBcd
True
False
This special param has been deprecated and will be ignored as of pgExpress 4.0. Please refer to BorlandCompatible for a better solution.
MapUnknownAsString
True
False
If True, unknown/unsupported field types such as point will be mapped as strings.
ArrayAsString
True
False
If True, arrays will be mapped as strings. If False, they will be ignored (hidden).
ByteaMode
AsGraphic
AsBlob
AsVarBytes
This parameter controls to which type the bytea fields get mapped. Check Bytea fields as BLOBs for more details. For compatibility with pre-v3.50 behavior(TVarBytesField, set this to asVarBytes. New in version v3.50.
Int8Mode
AsInt8
AsBcd
AsString
AsInt4
Ignore
AsInt8
The field will be mapped as Int8 using a hack (default).
AsBcd
The field will be mapped as TFMTBcdField.

Note

This is the pgExpress Driver1.X default setting, but is deprecated now (except in this situation).
AsString
The field will be mapped as string
AsInt4
The field will be mapped as Int4. Values are calculated using the following formula:
Int4Value := Int8Value mod High(Int4))
Ignore
The Int8 field will be ignored (hidden).

Notes:

  • Usage of this special parameter is DEPRECATED due to the introduction of the new default parameter AsInt8, which eliminates the Int8 typecasting need, except in this situation.
  • Please check Native Int8 support for more details.
  • On protocol 3.0+ drivers, this parameter will be ignored, since they can map to int8 field natively.
QuoteObjects
True
False
If True, quote objects names. To this setting to take effect, the connection must be reopened (if already opened of course). An example of unquoted and quoted query:

Example 2.1. Quoted and unquoted queries

select typname from pg_type; -- unquoted version
select "typname" from "pg_type"; -- quoted version

Please note that quoted objects names are case sensitive for PostgreSQL. The query above written like this would fail:

db =# select "typname" from "Pg_type";
ERROR: Relation "Pg_type" does not exist
                
TypesCachingMode
Default
Once
Connection
Cursor
This setting will control how often the types from PostgreSQL will be loaded and mapped into VCL/CLX types. Of course the less times they are loaded, the faster the application will be. The default setting should be OK for most applications (unless you do types manipulation).
Default
Currently, the same as "Once"
Driver
Types will be mapped only once and cached for later use.
Connection
Types will be remapped for each connection open.
Cursor
Types will be remapped for each new Dataset retrieved from the server.

Obs:

The PostgreSQL database has a flexible types support; that means we must retrieve the types information before we know what each type name means. This information is retrieved from the pg_type catalog and then mapped into actual dbExpress/VCL types by the pgExpress driver. Please refer to your PostgreSQL documentation for more details.
GetExtendedFieldsInformation
True
False
If True, will retrieve extra information about the fields in a table (for single table queries). That will allow the pgExpress Driver to determine if a field can be null (ISQLCursor.IsNullable()) or are automatically generated by a sequence the server (ISQLCursor.IsAutoIncrement()). Few applications should need this setting and they can be manually added to the TFields list representing each physical field. Since this will add a new query overhead for each cursor (TDataset) retrieved, slowing down the operation, it's adviced not to use it unless you need the information (for instance, on situations where you don't know the structure of the table that is going to be open).
ServerDecimalSeparator (char)

The pgExpress Driver should automatically detect your locale settings and use the appropriate decimal separator. However, if you want to force some specific value, this options is available. Set it to the char you want to be the decimal separator (usually either "." or ",").

However, since the "," is the options separator, you'll need to escape that char, like this:

ServerDecimalSeparator = \,

Another exemple:

ServerDecimalSeparator = .

See also ServerDecimalSeparator.

BlockRead
True
False

If True, the pgExpress Driver will use Fetch Cursors to retrieve the records from the server. The standard RowsetSize param (check your Kylix/ Delphi documentation) will determine the number of rows retrieved on each operation.

It is required to use this parameter to read the records in blocks since the pgExpress Driver will have to use a totally different method to retrieve the records from the server. Please refer to the section for more details.

UseQualifiedNames
True
False

If True, the pgExpress Driver will return qualified names on metadata retrieving, such as public.MyTable, pg_catalog.abstime, etc.

This option will only work PostgreSQL 7.3 which supports schemas.

RestrictedNameSpace
True
False
Controls which metadata is retrieved. If True, only objects in the current namespace search path will be retrieved. If False, all objects will be retrieved, regardless of which namespace they are in.
RequireSSL
True
False
If True, will only make a connection to the server in SSL mode. This option will only work with a SSL enabled libpq (currently only under Linux).
ShowOID
True
False

If True, the pgExpress Driver will return the OID field in the list of fields for a table (ISQLConnection.getColumns()).

See also this FAQ entry on OIDs usage with pgExpress.

ConnectionTimeout X Allows to specify connection timeouts (X in seconds). It needs libpq v7.3 or above (included with pgExpress Driver). This parameter is an integer value.
AutoRecover
True
False
If True, the pgExpress Driver will automatically try to detect if the connection has been broken and recover it automatically and continue processing. If it is sucessful, the whole operation is fully transparent to the user. If not, an appropriate error message will be displayed.

Note

This feature is avaiable only on the registered version of the driver.
RetainCursor
True
False

Controls the Retaining Cursors behavior.

If True, the pgExpress Driver will retain the cursor for the previous SELECT statement and return it if a previous dataset record is acessed again, instead of running the whole query again (dbExpress behavior). No matter how many times the same query is run again, always the same result set is returned (from the internal cache).

Note

This setting will be ignored if Fetch Cursors are being used.
BlobWriting
True
False
If True, the pgExpress Driver will allow Blob (Large Objects) writes. Blob writing is a delicate issue; just activate this setting if you read Section 6.7.1, “Large Objects (BLOBs)”. Registered users only.
LogDeclareFetch
True
False

If True, the pgExpress Driver will log (into TSQLMonitor) the DECLARE/FETCH commands executed internally as it requests rows from the server. The reason for this special param is that those commands could fill the logs with information not necessary to everybody; you can filter them setting it to False.

An example of unfiltered output (LogDeclareFetch=False):

Starting transaction for DECLARE/FETCH
Starting transaction
>> BEGIN;
>> DECLARE pgeCursor CURSOR for select * from pg_type;
>> FETCH 50 FROM pgeCursor
>> FETCH 50 FROM pgeCursor
>> FETCH 50 FROM pgeCursor
>> FETCH 50 FROM pgeCursor
>> FETCH 50 FROM pgeCursor
Closing cursor pgeCursor
>> CLOSE pgeCursor
Ending DECLARE/FETCH transaction
Rolling back transaction
>> ROLLBACK;

The same operation, but filtered (LogDeclareFetch=True):

>> BEGIN;
Rolling back transaction
>> ROLLBACK;

For more info on DECLARE/FETCH cursors, check Section 6.2, “Fetch Cursors”.

Registered users only since depends on Section 6.2, “Fetch Cursors”
Language (none) If empty, the pgExpress Driver will assume the language to be used is English. Otherwise, it is one of the entries of the Supported languages table table.
Borland Compatible False If True, the pgExpress Driver will try to be more compatible with the behavior of Codegear dbExpress drivers, mapping NUMERIC values like Codegear does.
UnicodeAsWideChar False If True, the pgExpress Driver will map string (CHAR, VARCHAR, TEXT) fields as TWideString, when using UNICODE client charset.

Note

This parameter is only meaningful for dbExpress protocol 3.0 and later applications, whose can map to TWideString.

DBX4Compatible (auto) If True, the pgExpress Driver will get into dbExpress 4 compatibility mode. Among other things, NUMERIC/DECIMAL fields will be mapped as TBcdField instead of TFMTBcdField. Please read ??? for further information.

Note

This parameter is only meaningful for dbExpress protocol 3.0 and later applications, running under dbExpress 4.


On older pgExpress Driver versions, these parameters used go into the dbxdrivers(.ini) file. But since version 1.5, they go after the Database parameter in the dbxconnections(.ini) parameter, separated by commas. On Delphi 7 or later, they can also go on the Custom String parameter.

Example 2.2. Special Parameters usage

[OfficeServer]
Database = sales,TextAsMemo = False, Int8Mode = AsString

[PGEConnection]
Database = sales, ArrayAsString = False, QuoteObjects = True, GetExtendedFieldsInformation = False

On Delphi 7, using the new Custom String section (works the same way as above, but this section was made for using with special params):

Example 2.3. Special parameters usage with the Custom String param

[PGEConnection]
Database = sales
Custom String = ArrayAsString = False, QuoteObjects = True, GetExtendedFieldsInformation = False

If you don't want to use any special parameters (as most users will), specify the Database parameter alone, normally:

[OfficeServer]
Database = sales

Of course these parameters could also go in the TSQLConnections. Params property as any other dbxconnections(.ini) parameter:

SQLConnection1.Params.Add('Database = sales,TextAsMemo = False,Int8Mode = AsString');

Or on Delphi 7, using the new Custom String section:

SQLConnection1.Params.Add('Custom String = ArrayAsString = False, QuoteObjects = True, GetExtendedFieldsInformation = False ');

Unhappily, due to the way dbExpress was designed on Delphi 6 and Kylix 1/2/3 , there can't be real custom parameters from VCL/CLX to the driver, so misusing the Database parameter was a hack that we had to do to allow custom params. Even on Delphi 7 only a single Custom parameter (Custom String) can be specified.

5.3. Custom Info

"Custom Info" are methods that can be used to retrieve information from the driver that otherwise could not be retrieved. They will only work with Delphi 7 or newer which implements the eConnCustomInfo interface.

For easy implementation of these interfaces, please use the corresponding functions from the pgeDriverUtils.pas unit.

Table 2.4. Custom Info Interfaces

Information Meaning Function
GetPGVersion Returns the PostgreSQL server version as a float. GetPGVersion
TTY Allows setting or retrieving file or TTY for optional debug output from the backend server. Set before connecting. GetTTY
BackendPID Will retrieve the PID of the process of the connection in the backend server. GetBackendPID
Online Will return True if a connection to the server exists. This implements the eCommOnline interface. GetOnline

6. Advanced Features

6.1. Stored Procedures Support

As most PostgreSQL users know, it does not have stored procedures support. Instead, it has a more flexible mechanism called Functions (created by CREATE FUNCTION statements).

The pgExpress Driver allows using of functions as stored procedures.

An usage example:

Example 2.4. Stored Procedures usage

procedure TForm1.Button1Click(Sender: TObject);
begin
  with SQLDataset1 do
  begin
    Close;
    CommandType := ctQuery;
    CommandText := 'create or replace function Test1(int2, int2) returns'
      + ' int2 as ''select $1 + $2;'' language ''SQL'';';
    ExecSQL;
    CommandType := ctStoredProc;
    // This MUST be before setting paramaters.
    // VCL clears Params on setting CommandText.
    CommandText := 'Test1';
    Params[0].Value := 10;
    Params[1].Value := 20;
    ExecSQL;
    ShowMessage(Params[2].AsString); // Will display 30
  end;
end;

6.2. Fetch Cursors

PostgreSQL supports a feature named Fetch Cursors. These special cursors allow the records to be retrieved from the server in smaller sets then the defaulbehaviort, which is retrieving the full recordset. To achieve this, the the PostgreSQL DECLARE and FETCH commands are used. This can accelerate the queries response in some situations, specially when the connection to the server is fast and the recordset is large. Also, Fetch Cursors do not need the whole query to be processed: they can start retrieving data as soon as the requested number of rows is available. Finally, Fetch Cursors will consume less memory then regular cursors because fewer rows stays in memory each time.

As of version 1.60, the pgExpress Driver features automatic FETCH cursors. The only thing needed is setting the special param BlockRead; however, you probably will want to change also the RowsetSize param (please check your Kylix/Delphi documentation) if you want (as of Delphi 6/7 and Kylix 1/2/3, default VCL/CLX value is 20).

Internally, the pgExpress Driver will DECLARE a cursor with a unique name (per transaction) for each dataset and use FETCH commands as their rows are requested. When the dataset is freed, it's cursor will be closed.

The number of rows retrieved on each internal fetch operation is given by the RowsetSize param. A negative RowsetSize param will issue a FETCH ALL command, what actually does not differ much then a regular query without use of a FETCH command: all rows will be retrieved at once.

Usually larger values, like 50 or 100 (or even more, depending on your environment), would give a better performance. Please try and see what value is best for your application, but have in mind that each FETCH command means a separated query and that could slow down dataset scrolling over slower connections.

A typical dbxconnections(.ini) setup would be:

[PGEConnection]
BlobSize=32
Database=localhost/mydb,BlockRead=True
DriverName=PostgreSQL
Password=temp123
User_Name=foo
RowsetSize=200

Internally, the pgExpress Driver will automatically execute all SQL commands needed to use Fetch Cursors (DECLARE and FETCH); all operations are transparent to the user.

An additional, good side effect of using Fetch Cursors is that the overall memory used is much less that if you retrieve all rows at once, due to libpq caching. For large datasets, using this setting is a smart option. Please check Q: 7 for more details.

Notes:

  • Set TClientDataset.FetchOnDemand to True. If you don't set TClientDataset.FetchOnDemand to True, Fetch Cursors will be worthless because the TClientDataset will be caching all rows in memory. Of course when not using a caching grid such as TClientDataset, this is not needed.
  • Don't sort data on the client. If you sort the data in the client such as in a TClientDataset or in a TDBGrid components, all data will have to be retrieved in order to perform the sorting.
  • Monitor your connection. Always monitor your connection by attaching a TSQLMonitor to your TSQLConnection and log the communication between both into a file. In the case of DECLARE/FETCH cursors, the specific commands for them will be logged in there in case everything is running fine.
  • Registered users only. The Section 6.2, “Fetch Cursors” feature is available only for registered users.
  • The RetainCursor Special Parameter will be ignored if Fetch Cursors are in use. For more details on the inners of Fetch Cursors, please refer to the follow PostgreSQL documentation links:
  • Open transactions on older servers. As of PostgreSQL7.2, a transaction is needed in order to user Fetch Cursors; the pgExpress Driver will start a transaction automatically if one isn't already open. If you want to control the transactions behavior, open a transaction using TSQLConnection.StartTransaction before opening the cursor.

6.3. Authentication

As of PostgreSQL 7.3, three authentication methods are available: password, crypt and md5.

Since the pgExpress Driver is libpq based, use these three methods are automatic, and will follow what you have defined on the pg_hba.conf file (please check here for details).

We advice using the MD5 method (PostgreSQL 7.2 and above), unless you are using SSL or other encryption wrapper in your connection to the server.

6.4. Automatic numeric format detection

The pgExpress Driver has the ability to automatically detect the numeric format used on you server; namely, the Decimal and the thousands separators. There should be no need to set numeric formats manually, but in case you want or need, try the ServerDecimalSeparator special parameter.

In case the automatic detection do not work for you, please mail us at support@vitavoom.com

6.5. Native Int8 support

Since dbExpress (pre-protocol 3.0) does not support int8 types natively, the 1.X series of the pgExpress Driver used to map them as TBcdField fields by default (AsBcd).

As of pgExpress Driver v2.0+, int8 fields are mapped directly to TLargeintField fields using an internal hack. However, that hack will not work on all situations; specially if you need to write to int8 fields, map them as type TBcdField using the AsBcd special param and everything will work as you expect on the Delphi/Kylix side.

If you, however, need only read-only access to the int8 fields, you can use that hack and enjoy a native Int8 suppport instead of mapping to another type.

Important note about dbExpress usage with Int8 fields

Note that Int8 fields support is still not official in dbExpress as of this is written. While they will work most of time, the TIndexDefs create on these fields will not be correctly handled by VCL. You can get "Key violation" messages when trying to insert new values in this field, even if the values differ. To prevent this, you can try any of the following workarounds:

  1. Map Int8 fields as a type that is natively supported by dbExpress such as BCD using AsBcd. Avoid using AsString because this would sort the field as string and not as a number (i.e. '10' would be before '2').
  2. Disable metadata retrieving by setting GetMetadata to False on your TSQLDataset . In older versions then D7, it's the same as enabling NoMetadata.
  3. Delete the IndexDef generated automatically by dbExpress. After opening your ClientDataset, call ClientDataset1.IndexDefs.Delete(0) for removing that IndexDef. However, this will make the field unindexed; the exception will not be raised even when you insert duplicate values in the field.

6.6. Retaining Cursors

The lack of a ISQCursor.First() interface for dbExpress cursors make it necessary to run any query twice if you want to access a previous record again; the dbExpress technology is currently forward-only. Of course, Client Datasets (TCustomCachedDataset descendants) will cache records so random access is possible; but non-cached SQL Datasets (TCustomSQLDataset descendants) will make the query run again.

The pgExpress Driver implements an experimental setting, RetainCursor, that will make non-cached datatasets access MUCH faster to access from the second time, since the records will be retrieved from the internal libpq cache instead of being retrieved once again from the server. Basically, if RetainCursor is True, the query is a select query and the query is the same as the last one executed, the results displayed will be the same from the cache.

This behavior is controlled by the RetainCursor Special Parameter. If you are using RetainCursor = True and want a particular query to be trully executed again, instead of retrieved from the cache, add a '!' char to the beginning of the query (it will be automatically stripped by the pgExpress Driver):

!select * from pg_type;

Note

This setting will be ignored if Fetch Cursors are being used.

6.7. BLOBs Support

As of pgExpress v3.50, there are three kinds of BLOBs supported, according to their mappings:

  • Large Objects -> ftBlob/ftBinary
  • Bytea ->ftBlob/ftGraphic
  • Text -> ftBlob/ftMemo

Detailed explain of these modes follows below. For very large streams, the best approach is to use Section 6.7.1, “Large Objects (BLOBs)”; however, for small (around 1-2Mb or even more), such as pictures, it's much easier and cleaner to use Bytea fields as BLOBs.

6.7.1. Large Objects (BLOBs)

Large Objects implement file-like I/O operations on PostgreSQL through a complicated API. The pgExpress Driver allows using them automatically through the regular dbExpress API.

Important upgrade Note:

As of pgExpress v2.31, we had to make some changes to the way pgExpress handles Large Objects and also changes to this documentation. Due to a bug in PostgreSQL up to v7.4 (PQftype() won't return the current oid for a domain, but for it's defined type instead) the way to create the 'lo' type has changed as shown below; it used to be:

create domain lo oid

but that will not work as it should due to the way the backend protocol works.

If you have a production database using the 'lo' type/domain declared in a different way then below, we suggest to pg_dump the database structure and data separately, then change the struct dump script to create the 'lo' type as shown below, and finally recreate the database structure with the new 'lo' type definition and restore the data.

6.7.1.1. Large Object field declaration

The Large Object 'lo' field type isn't declared by the default in the PostgreSQL distribution, so we must do it manually. However, as of PostgreSQL 8.0, Windows users used to install the contrib modules from the installer might already have installed the 'lo' contrib module, which adds a compatible lo type, and these steps will not be necessary. Of course, users from other platforms that installed that contrib module will also have that type automatically created.

So, before creating the lo type, check if it isn't already created:

Example 2.5. 

howe=# select oid, typname from pg_type where typname='lo';
    oid  | typname
  -------+---------
   17245 | lo
  (1 row)

The Large Object fields declaration must follow the method introduced by the PostgreSQL ODBC driver: a 'lo' type. This type can be created easyly using the following query (PostgreSQL 7.3 and above):

CREATE FUNCTION lo_in(cstring)
     RETURNS lo
     AS 'int4in'
     LANGUAGE 'internal' WITH (ISCACHABLE, ISSTRICT);
  
  CREATE FUNCTION lo_out(lo)
     RETURNS cstring
     AS 'int4out'
     LANGUAGE 'internal' WITH (ISCACHABLE, ISSTRICT);
  
  CREATE TYPE lo(
     internallength = 4,
     externallength=10,
     input = lo_in,
     output = lo_out,
     alignment = int4,
     default = '',
     passedbyvalue
  );
  CREATE CAST (lo AS oid) WITHOUT FUNCTION;

Note

Code originated from a Hiroshi-Saito post.

...or (PostgreSQL 7.2X and below):

create type lo(
    internallength=4,
    externallength=10,
    input=oidin,
    output=oidout, 
    default='',
    passedbyvalue
  );

You can then use this type normally on your tables:

Example 2.6. Creating a table with a Large Object

create table employee(id integer, name varchar(30), picture lo);

Note

Some of this code is part of the PGSQL ODBC - FAQ
6.7.1.2. Using Large Objects (BLOBs)

The pgExpress Driver can read Large Object (BLOB) fields without problems; however, due to the way the dbExpress technology was designed and the particular implementation of Large Objects on PostgreSQL, the pgExpress Driver has problems on updating Large Object fields.

PostgreSQL refers to Large Objects using a OID that points to the the real data.The libpq library needs this OID to do all sort of operations on the Large Object fields. The problem is that the dbExpress API will be expecting only the BLOB field's data; the OID information has no way to be stored. After the BLOB field is processed internally by the VCL/CLX and is sent back to the pgExpress Driver for being stored in the database, the original OID of the Large Object can't be retrieved, so pgExpress won't know which BLOB is refers to. This means that we can't alter the original Large Object, and if we create a new Large Object, the original Large Object will end up with as a orphan Large Object (a LO that exist but is not referenced by any rows, wasting disk space), unless of course another row refers to the same LO, what is not a common situation.

At Vita Voom Software™, we understand that Large Objects support it is crucial for some users and thus we have the following suggestion as a workaround to this problem, which affects also the JDBC and ODBC drivers:

Notes:

  • This method has the disavantage of wasting OIDs. This should never be a problem since more then 4 billions (2^32) of OIDs are avaiable. However, if you want to save OIDs, the lo_clean() function above could easily be modified to reuse the old OID value in the case of a UPDATE query, by adding an statment such as:
    update pg_largeobject set loid=old.oid where loid=new.oid
    
  • The contrib/lo directory on the PostgreSQL distributions contains code that helps avoiding orphan Large Objects; you might be insterested in using it, or even reading the docs for more background on the subject.
  • As of PostgreSQL 8.0, a transaction must be open in order to work with Large Objects; but if there is none open, the pgExpress driver will open one itself, and rollback it when done. In order to avoid this open/close transaction overhead, and having possibility of commiting the trsansaction, it's better to open explicitly a transaction and commiting/rolling back after you're done.
  • It will probably be much easier and flexible to work with bytea fields instead of Large Objects, since it's API is very unflexible and complicated. Check the ByteaMode Special Param for more details.
  1. Create your table normally, including the BLOB field (please read this section about BLOB fields declaration):

    create table lo_test(id serial, image lo);
    
  2. Create a trigger and function that will delete the Large Object if their values are changed (replace the b fieldname for your real field name):

    Function:

    create or replace function test_lo_clean() returns trigger as '
        declare
          lo_oid oid;
        begin
          -- If it is an update action but the BLOB (lo) field was not changed, dont do anything
          if (TG_OP = ''UPDATE'') then
            if (old.image = new.image) or (old.image is null) then
              return new;
            end if;
          end if;
          select into lo_oid loid from pg_largeobject where lo_oid = oid(old.image);
          if found then
            perform lo_unlink(lo_oid);
          end if;
          return new;
        end'
      language 'plpgsql';
    

    Trigger:

    create trigger lo_cleanup
      after delete or update on lo_test -- must be after to avoid deleting the Large Object if record is not deleted
      for each row execute procedure test_lo_clean();
    

    Note

    The function above uses the pl/PgSql language, which must be created in the datbase if it wasn't already. This can be accomplished easily through the following command (at the shell prompt):

    $ createlang -d dbname plpgsql
    

    For more details on creating languages, please check here.

    This trigger will avoid that orphan Large Objects are left on the table. Note that triggers are fast; in fact, referential integrity is implemented internally in PostgreSQL using them. If you want to try another code to do it, feel free; all you need to do is ensure no orphan OIDs are left on the pg_largeobject table.

    You might have to make some small changes to the test_lo_clean() function to reflect your actual table and field names, if you have large objects reused in more then one field/record, etc.

Hopefully the PostgreSQL developers will introduce a new API for handling Large Objects that does not suffer from these limitations.

Tips:

  • All Large Object operations must take place inside transactions. If one isn't started, the pgExpress Driver will open one automatically, and close it after finishing reading (or writing, but VCL/CLX always resolve updates inside transactions, so this usually won't be a problem). This transaction opening/closing adds some considerable overhead if you do it for several fields. Hence, always start a transaction prior to using Large Objects.
  • As os PostgreSQLv8.0, Large Object operations aren't compatible with asynchronous connections. The pgExpress Driver will automatically switch for a blocking (synchronous) connection during the Large Object operations and switch back to non-blocking after finished.
  • If you have orphan Large Objects in a table and want to clean them, try the following approach:
    select lo_unlink(lo_column) from mytable;
    
  • For a demo on BLOB fields, try Demos/Fishfact from the pgExpress Driver distribution.

6.7.2. Bytea fields as BLOBs

As of pgExpress 3.50, it is possible (and actually the new default behavior) to map bytea fields as ftBlob (ftGraphic or ftBinary) through using theByteaMode Special Param. This makes much easier to use BLOB fields on pgExpress since there is no need to use the Large Objects API.

While this is activated by default, it could conflict with older datasets that are mapping bytea fields as TVarBytes fields, which was the old pgExpress behaviour. To force mapping bytea fields as TVarBytesField again, set the special param ByteaMode Special Param to asVarBytes. To completely disable Section 6.7.1, “Large Objects (BLOBs)” support by mapping bytea fields as ftBlob>/ftBinary, set the special param ByteaMode Special Param asBlob.

Remember that bytea chars greater that 128 must be quoted as octals (ex: \343), what will make streams be greater in size (4x more for those chars that have to be quoted) and also waste more bandwidth - a mean of about 2.5x for a random stream. For small streams, this should not be a problem; however, for greater streams, consider using Section 6.7.1, “Large Objects (BLOBs)”. This protocol behavior is internal to PostgreSQL and the pgExpress Driver must conform to it.

Important:

When assigning a value to a bytea TParam which is mapped as ftGraphic, you'll tipically use the TParam.asBlob property, or the SetBlobData method.

After doing it, do not forget to set the TParam.DataType to ftGraphic, because these methods set TParam.DataType to True; otherwise, the fields will be try to be saved as Large Objects, and that would be the source of weird errors. Example:

Example 2.7. 

with Dataset1.ParamByName('value') do
begin
  ParamType := ptInput;
  AsBlob := aData;
  DataType := ftGraphic;
end;


Again, this is only needed by bytea fields mapped as ftGraphic, on the specific conditions mentioned above.

6.7.3. TEXT fields as BLOBs

To allow easy use of TEXT fields, the ppgExpress Driver maps them as ftBlob/ftMemo by default; they can have arbitrary lengths, contrary to regular string (ftString) fields, whose must have a specific length.

VARCHAR fields without length specifier behaves exactly like TEXT fields, and will be mapped as such. See also TextAsMemo and Q: 11 for more details.

Important:

When assigning a value to a ftMemo TParam, use always the TParam.asMemo property (and not TParam.asBlob, which is intented to work with binary blobs(subtype ftBinary).

6.8. SSL Support

PostgreSQL has built-in support for SSL. However, on the backend (client) side, we depend on libpq support for actually encrypting the connection. The Linux libpq suplied with the pgExpress Driver is SSL-enabled, but the Windows version is not to keep the libpq small. If you want a SSL-enabled libpq, use the one supplied in the PostgreSQL for Windows distribution.

There are, however other ways to do it, even if your libpq is not SSL-enabled. The simplest is making a tunnel using either SSH or Stunnel. Please go to the referring site for more details.

6.9. NOTICEs support

PostgreSQL by default will print NOTICE messages (generated by the server and inside functions by statements such as RAISE NOTICE) in the server's standard output. The pgExpress Driver implements a hook which allows those messages to be logged along other regular messages so that a TSQLMonitor component will be able to log them all automatically.

Note

The NOTICE messages will set CBInfo to traceVENDOR on the OnTrace/OnLogTrace events.

6.10. Asynchrounous connections

The pgExpress Driver has asynchronous connections support. Their advantage is that a query could be cancelled while in execution in the server. Other then that, there is no real advantage on then.

To activate asynchronous support on pgExpress, set this on your dbxconnections.ini file (or equivalent):

BlockingMode=False

To force synchronous connections, whose are more compatible in general, use:

BlockingMode=True

If you have problems with async support, please switch to synchronous mode.

6.11. Canceling a query

Whenever you send a query to the PostgreSQL server, it can delay a long time to return a result to your application. Typical cases include a very long resultset, lots of computations/calculations, or even a function hangup/infinite loop. It is nice to let you user cancel a query if they want to, thus returning control to your program, and quitting things nicely in the server side. The way to accomplish this is by using asynchronous connections, and that can be cancelled by calling the PQrequestCancel function.

The pgExpress Driver wraps that API nicely in the pgeDriverUtils.CancelQuery function. Calling it will make the server try its best to cancel the currently query and return control to the client application. This has the same effect as pressing Ctrl+C in the psql console.

Chapter 3. Localization

1. Multibyte, UNICODE and Locales

The pgExpress Driver can handle Multibyte/UNICODE/Locales in the following ways:

  1. Using the built-in dbExpress Locale support.

    Basicly, you just would have to set in your dbxconnections file:

    LocaleCode = XXXX
    
    XXXX is the TLocaleCode type value for your Locale. For instance:
    LocaleCode = 1041
    

    would set the current locale to 1041 (= Japanese).

    Check the Delphi help for TLocaleCode type, TSQLConnection.LocaleCode, and Driver parameters (you can use the help's 'Find' feature if you don't locate these easily).

  2. Using automatic PostgreSQL server-client conversion. The pgExpress Driver implements this by using the parameter in the dbxconnections(.ini) file (could also be a value in the TSQLConnection.Parameter property).

    Since dbExpress do not provide custom parameters support, and it does not support a ClientCharset parameter, we have to use the following hack: providing both the Server and Client encodings ServerCharset parameter (the client encoding is optional). The format used is:

    ServerCharset = ServerEncoding[/ClientEncoding]
              
    

    Examples (you will actually use only one line at once):

    ServerCharset = EUC_JP
    ServerCharset = EUC_TW/UNICODE
              
    

    If no client/server encodings are set, defaults are using depending on the database encoding.

    The valid encodings, from the PostgreSQL documentation, are:

    Table 3.1. PostgreSQL Encodings

    Encoding Description
    SQL_ASCII ASCII
    EUC_JP Japanese EUC
    EUC_CN Chinese EUC
    EUC_KR Korean EUC
    EUC_TW Taiwan EUC
    BIG5 Chinese BIG5
    UNICODE Unicode (UTF-8)
    MULE_INTERNAL Mule internal code
    LATIN1 ISO 8859-1 ECMA-94 Latin Alphabet No.1
    LATIN2 ISO 8859-2 ECMA-94 Latin Alphabet No.2
    LATIN3 ISO 8859-3 ECMA-94 Latin Alphabet No.3
    LATIN4 ISO 8859-4 ECMA-94 Latin Alphabet No.4
    LATIN5 ISO 8859-9 ECMA-128 Latin Alphabet No.5
    LATIN6 ISO 8859-10 ECMA-144 Latin Alphabet No.6
    LATIN7 ISO 8859-13 Latin Alphabet No.7
    LATIN8 ISO 8859-14 Latin Alphabet No.8
    LATIN9 ISO 8859-15 Latin Alphabet No.9
    LATIN10 ISO 8859-16 ASRO SR 14111 Latin Alphabet No.10
    ISO-8859-5 ECMA-113 Latin/Cyrillic
    ISO-8859-6 ECMA-114 Latin/Arabic
    ISO-8859-7 ECMA-118 Latin/Greek
    ISO-8859-8 ECMA-121 Latin/Hebrew
    KOI8 KOI8-R(U)
    WIN Windows CP1251
    ALT Windows CP866

    The values for valid server encoding and client encodings and their detailed descriptions are in the PostgreSQL's documentation at Multibyte Section ). Internally, pgExpress will interpret the values in the following way:

    1. If you provide only a ServerEncoding, the pgExpress will try to setup a default ClientEncoding for it. The default ClientEncoding will be set by the libpq the same as the ServerEncoding, except for the UNICODE and MULE_INTERNALServerEncoding, whose have no default value.
    2. If you provide a ClientEncoding parameter, it will be set regardless of what is defined in the ServerEncoding parameter. If you want to set only a ClientEncoding value, just omit the ServerEncoding value (but include the / separator), like this:
      ServerCharset = /latin2
      

      This will set the ClientEncoding to latin2 regardless of the ServerEncoding.

      Other examples:

      ServerCharset = latin2
      

      The libpq will set the ClientEncoding to latin2 because it's the default encoding for the latin2 ServerEncoding.

      ServerCharset = latin2/latin3
      

      This will set the ClientEncoding to latin3.

    3. As of BDS 2006 and pgExpress 4.x, there is also UNICODE support thorugh use of TWideStringField fields. To use UNICODE, the following requirements must be met:

      • Use the pgExpress Driver for dbExpress protocol 3.0
      • Set the application's client charset to UNICODE. If the database is already UNICODE, and protocol 3.0 driver is used, this will be automatically set.
      • Set the UnicodeAsWideChar special param so that the string fields are mapped as TWideStringField fields; otherwise, they would be mapped as TStringField fields.

      Note

      Unhappily as of BDS 2006 there is no TWideMemo support for dbExpress. The VCL/CLX will remap any fields defined as such as ftBlob/ftBinary.

If you have problems opening bases with UNICODE encoding ("Invalid encoding" errors), add a client encoding to your dbxconnections(.ini) entry, that will convert from multibyte to single byte encoding, according to your locale, such as:

ServerCharset = /latin1

...or:

ServerCharset = /latin1

2. Multilanguage Driver

The pgExpress Driver distribution contains two versions: a standard one, English only, and a Multilanguage version. Functionality is identical, except that the standard only contains the English (enUS) language, and the multilanguage version contains all languages from the table below:

Table 3.2. Embedded languages in this release (multilanguage driver only)

Language Language Code
English enUS
Portuguese (Brazilian) ptBR

This by no means limits the languages that can be used with the pgExpress Driver; you can always do a new translation and load it. Instructions are in the next section.

Note

The English language will be used by default, unless some other valid language is used.

To set localized messages, choose among the following methods:

  1. Do nothing!... If you use the multilanguage driver and it already has the same language reported by your OS, it will be loaded automatically. The same will happen if you have a directory locale\LL\LC_MESSAGES with a xx_XX.mo file that matches your language. Check the dxgettext documentation for details.

    Use the ErrorResourceFile parameter, with the xx_XX.mo language file. This parameter will be passed by the VCL/CLX to the pgExpress Driver, so it's the recommended standard way to handle languages.

  2. Use the Language special parameter. Set it to match one of the language codes of the Supported languages table.

    Example 3.1. 

    [PGEConnection]
    BlobSize=32
    Database=localhost/mydb,Language=deDE
    DriverName=PostgreSQL
    Password=temp123
    User_Name=john
    

    Note

    This example assumes the deDE (German) language is embedded in the multilanguage driver.

    These entries represent the languages embedded on the multilanguage driver. If the language is not supported by the driver, or if you're not using the multilanguage version of the driver, this parameter will be ignored.

  3. Call the PGEDriverUtils.SetLanguage() function, passing the language code as parameter (embedded languages only).

If you want to translate the pgExpress Driver to another language not listed in here, just translate the default.po (English) file. To customize/fix and existing translation, just edit it's .po file. Check the next section for details.

A language code usually consists of a two-letter lowercase language code, an underscore, and a two-letter uppercase country code. On Windows, this is not case sensitive, but on Linux, it is. German in Germany becomes de_DE, English in England becomes en_GB, etc.

If you translate to a new language, please consider contributing it to other users by sending the file to us. I this case, fill your translator's data at the .po file header if you want.

Tip

You might want also to translate the libpq library and/or PostgreSQL itself to get translated PostgreSQL error messages. Please refer to the PostgreSQL's documentation for details.

3. Translating the pgExpress Driver

Translating the pgExpress Driver to another language is easy:

  1. Copy the default.po file from the languages distribution with a new name.

    Note

    This file is in a separate languages package; a download our site.
  2. Translate the msgstr entries to match those of the language you want to translate to. Use a unicode-enabled editor (such as Vim, Unired or poEdit. Do not modify the msgid entries, and keep the %-escaped chars. They will be formatted internally by the Format() function.
  3. Use the msgfmt tool from the gettext or dxgettext distributions to compile the resource file into a .mo file.
  4. Copy the compiled .mo file anywhere you want and point to it using the Language to activate the translation. You can also add it to locale\LL\LC_MESSAGES and it will be automatically found by the Language or even loaded if the current reported locale matches it. Don't forget you must be using the multilanguage driver for this to work. If you have a new/fixed pgExpress Driver translation .po file and don't know, want or just can't compile it, send it to us at support@vitavoom.com and we might compile it for you.

For details on the gettext functionality, check the following sites:

gettext - the official gettext site
dxgettext - the official dxgettext site. dxgetxt is used internally by the pgExpress Driver to provide the gettext functionality

Chapter 4. PGEDriverUtils.pas

The pgeDriverUtils.pas unit, in the Extras directory, adds some useful functions to retrieve/set information from the pgExpress Driver and the PostgreSQL server. This information is retrieved via callback functions and all or most of them are available in D7+ only which supports the eConnCustomInfo interface.

The function marked as "D7+" depend on the eConnCustomInfo and thus cannot be run on Delphi versions less the 7.0 or Kylix.

When using the protocol 3.0 pgExpress Driver, use the DBXPROTOCOL30 define in your project settings, compiler command line or at the top of the unit:

{$DEFINE DBXPROTOCOL30}

GetPGVersion

Returns the PostgreSQL version number as reported from the server.
function GetVersion(Connection: TSQLConnection): Extended;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

An Extended value containing the server database version.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.1. 

ShowMessage('The database version is ' + FloatToStr(GetPGVersion(SQLConnection1));

GetTTY

Returns the file or TTY debug for the connection.
function GetTTY(Connection: TSQLConnection): AnsiString;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

A string value containing the file or TTY, or '' (empty string) if none.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.2. 

ShowMessage('The debug file/TTY of this connection is ' + GetTTY(SQLConnection1));

GetBackendPID

Returns the server PID (process ID) (as on the server) for the connection. D7+ Only.
function GetBackendPID(Connection: TSQLConnection): Integer;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

An Integer value corresponding to the PID..

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.3. 

ShowMessage('The PID of this connection is ' + IntToStr(GetBackendPID(SQLConnection1)));

GetOnline

Returns the connection status: online or not. D7+ Only.
function GetOnline(Connection: TSQLConnection): Boolean;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

True if connected, False if not.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.4. 

ShowMessage('The connection is ' + IfThen(GetOnline(SQLConnection1), 'online', 'offline') + '.');

GetRetainCursor

Returns the RetainCursor status. D7+ Only.
function GetRetainCursor(Connection: TSQLConnection): Boolean;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

True or False, according to what is defined in the internal RetainCursor.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.5. 

ShowMessage('The RetainCursor status of this connection is ' + BoolToStr(GetRetainCursor(SQLConnection1)));

SetRetainCursor

Sets the internal RetainCursor value. D7+ Only.
procedure SetRetainCursor(Connection: 
        TSQLConnection; Value: Boolean);
      

Parameters:

Connection
The TSQLConnection component that is connected to the server.
Value
The value to set the internal RetainCursor flag to.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.6. 

SetRetainCursor(SQLConnection1, True);

GetLanguage

Returns the current language being used. D7+ Only.
function GetLanguage(Connection: TSQLConnection): AnsiString;

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Return Value:

The current language being used by the driver. This should be a 4-chars length string.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.7. 

ShowMessage('The current language is ' + GetLanguage(SQLConnection1));

SetLanguage

Sets the internal Language value. D7+ Only.
procedure SetLanguage(Connection: 
        TSQLConnection; Value: Boolean);
      

Parameters:

Connection
The TSQLConnection component that is connected to the server.
Value
The value to set the internal Language variable to.

Exceptions:

EDatabaseError is raised in case of an error.

Quick Info:

Supported Compilers: D7+
Category: Database Information
Unit: PGEDriverUtils.pas

Example 4.8. 

SetLanguage(SQLConnection1, True);

CancelQuery

Tries to cancel a query in execution, when in assynchronous mode. This will call libpq's PQrequestCancel function, and it will work just like it.

Parameters:

Connection
The TSQLConnection component that is connected to the server.

Exceptions:

None defined

Quick Info:

Supported Compilers: Category:
Query Execution Unit:
PGEDriverUtils.pas  

Example 4.9. 

CancelQuery(SQLConnection1);

Chapter 5. Ordering and Licensing

1. Ordering

You can purchase the Vita Voom SoftwarepgExpress Driver and the other Vita Voom Software™ products through our reseller, Shareit!, using your credit card or one among many other payment forms they support (Mastercard, Eurocard, VISA, Delta, JCB, Switch, Solo, Discover, American Express, Diner's Club, UK cheque, US check, Postcheque, International Money Order, Bank wire and PayPal). The purchase process is done through a secure web server; your personal details such as name, address and credit card number or bank account number won't be reveiled to anyone.

We shall send you your product through download link and/or email, as soon as Shareit! notifies us about your purchase and consider the transaction done.

To order the pgExpress Driver or any of our other products, please go to our Orders Page.

If you have any comments, problems or doubts about purchasing from us, we would like to hear from you at orders@@vitavoom.com.

2. Restrictions of the Demo driver

The demo version is a restricted version of the pgExpress Driver. The differences are:

  • The demo version only runs under the Kylix/Delphi/C++ Builder IDEs.
  • The demo version will only allow 15INSERT/UPDATE/DELETE statements per transaction.
  • The full version implements automatic recovery of broken connections.
  • The full version implements automatic DECLARE/FETCH cursors.
  • Only the full version allows BLOB writing.

3. License Agreement

This is the license agreement for the pgExpress Driver (SOFTWARE). BY INSTALLING, COPYING, OR OTHERWISE USING THE SOFTWARE, YOU AGREE TO BE BOUND BY ALL OF THE TERMS AND CONDITIONS OF THE LICENSE AGREEMENT.

Althought we are we know it works fine, and Vita Voom Software™ puts the maximum of its efforts to develop, support and enhance it, the Software provided under this License Agreement, including but not limited to libraries, source code, documentation, redistributables and other files are provided "as is", without warranties of any kind.

The Software is owned by Vita Voom Software™ and is protected by copyright law and international copyright treaty. Therefore, you must treat this Software like any other copyrighted material (e.g., a book), except that you may either make one copy of the Software solely for backup or archival purposes or transfer the Software to a single hard disk provided you keep the original solely for backup or archival purposes.

You may not alter any of the programs or accompanying files without Vita Voom Software™'s written permission. Any resale or commercial distribution of the Software is strictly prohibited, unless Vita Voom Software™ has given explicit written permission. You can, however, distribute the software as part of a program your company have produced.

You have the right to use the Software as set forth in this licensing agreement. You are not obtaining title to the Software or any copyrights. You may not sublicense, rent, lease, convey, modify, translate, convert to another programming language, decompile, or disassemble the Software for any purpose.

Finally, the software is provided on a PER DEVELOPER basis. You must buy a license for each developer who's using the pgExpress. Your license might be CANCELLED if you do not comply to the above statements.

3.1. Demo Version Restrictions

(The following applies only to the demostration ("demo") version of the Software.)

This version of the Software is a demonstration version. This means that you may use the Software for evaluation purposes only. You may use the Software to test whether it meets you demands. You must not distribute materials produced by the Software to computer systems different from the computer on which the Software is installed, regardless of how such a distribution takes place. You must not modify any material produced by the Software, including but not limited to computer files which where created as a result of the usage of the Software. You are not allowed to sell, rent, lease or otherwise use commercially files or parts of files which where created by the Software. The Software is equipped with a mechanism that prevents the full usage of the Software.

3.2. Disclaimer

VITA VOOM SOFTWARE™ MAKES NO REPRESENTATIONS OR WARRANTIES AS TO THE TRUTH, ACCURACY OR COMPLETENESS OF ANY STATEMENTS, INFORMATION OR MATERIALS CONCERNING THE SOFTWARE THAT IS CONTAINED ON AND WITHIN ANY OF THE WEBSITES OWNED AND OPERATED BY VITA VOOM SOFTWARE.

THIS SOFTWARE IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED INCLUDING BUT NOT LIMITED TO THE APPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. YOU ASSUME THE ENTIRE RISK AS TO THE ACCURACY AND THE USE OF THE SOFTWARE AND ALL OTHER RISK ARISING OUT OF THE USE OR PERFORMANCE OF THIS SOFTWARE AND DOCUMENTATION. VITA VOOM SOFTWARE™ SHALL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF VITA VOOM SOFTWARE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL VITA VOOM SOFTWARE™ BE LIABLE FOR ANY CONSEQUENTIAL, INCIDENTAL, DIRECT, INDIRECT, SPECIAL, PUNITIVE, OR OTHER DAMAGES WHATSOEVER, INCLUDING BUT NOT LIMITED TO DAMAGES OR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS, EVEN IF VITA VOOM SOFTWARE™ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES/JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY.

The entire contents of this this package is protected by Brazilian and International Copyright Laws. Unauthorized reproduction, reverse-engineering, hacking and redistribution of all or any portion of the code contained in this file is strictly prohibited and may result in severe civil and criminal penalties and will be prosecuted to the maximum extent possible under the law.

This package can be redistributed only under it's original form; no changes may be applied to it or it's contents.

If you disagree about any of these terms, you're not allowed to use the pgExpress Driver. Please remove the all copies of the Software from your system.

It is forbidden to use the Vita Voom SoftwarepgExpress Driver in products that in a way or other reproduce or extend the functionality of any Vita Voom Software™ product (namely but not restricted to the pgExpress Suite), unless they're for internal use of your own company. Again, distribution of such products based in pgExpress Driver is FORBIDDEN.

For more details, please contact Vita Voom Software™.

The pgExpress PostgreSQL dbExpress Driver and all it's related files are Copyright 2001- 2012 Vita Voom Software™.

Chapter 6. Notes

1. Known Issues

  • Int8 fields couldn't be properly supported in the past because dbExpress itself do not support them. The pgExpress Driver has a workaround for this by using a hack discovered by Peter Sawatzki (http://www.sawatzki.de) that allows native use of the Int8 type. Older ( 1.X) versions of the pgExpress Driver had option to remap Int8 fields as Bcd, Strings, Int4 or letting them as Unknown type. For compatibility reasons, these options are still available but the new default behavior on 2.X+ is mapping them as Int8 using the mentioned hack.

    Those who want the old behavior for compatibily reasons, use the Special Param Int8Mode = AsBCD.

  • The driver won't automatically retrieve the IsAutoIncrement() and IsNullable() interfaces unless you set the Special Param GetExtendedFieldsInformation. This is done to reduce an extra query overhead that would be necessary otherwise.

    You can always set these values directly in the TFields manually, of course.

  • The driver can't log the disconnection event because the VCL clears the pointer to the TSQLMonitor callback function before disconnecting, through a SQLConnection.SetOption() call.

  • Arrays support is provided by mapping them as strings (i.e., the same way PostgreSQL returns them). This is a delicated issue; arrays in PostgreSQL always have variable length, regardless of what is declared in the table definition (that is for documentation only). For instance, the following code is legal (psql 's output):

    test=#  create table array_test(a integer[2]); /*Declare a table with an array' */
    CREATE
    test=# insert into array_test values ('{1,2,3,4,5,6,7,8,9}');
    INSERT 7500763 1
    test=# select * from array_test;
    a
    ---------------------
    {1,2,3,4,5,6,7,8,9}
    (1 row)
    
  • ADTs can't be properly supported under current dbExpress implementation.

  • The pgExpress Driver was not tested in older (previous to 7.1) versions of PostgreSQL. If you test it on some older version, please tell us your impressions.

  • Since the VCL/CLX parses the colons (':') as being parameter delimiters, you need to use double colons in SQL syntax (or scape them with backslashes). Colons are used to do typecasts, as in the following code:

    select typelem::::int4 from pg_type; /*Instead of 'select typelem::int4 from pg_type;' */
    

    You can use the cast() function similary:

    select cast(typelem as integer) from pg_type;
    

2. Notes

  • String and VarBytes (bytea) fields limit is 32kb (when not mapped as BLOB), due to dbExpress limitations.
  • Codegear made a huge dbExpress/TClientdataset update on Delphi 7.1. If you are using D6/D7, we highly recommend you to upgrade to that version, or later.

Metadata notes:

  • The RECNO field for the getTables(), getIndices() and getProcedures() are actually the OID for each corresponding tuple, and not a sequential serie starting at 1.
  • In the ISQLMetadata.GetProcedures() interface, which is used by the TSQLConnection.GetProcedures() procedure, as of PostgreSQL7.3 we consider functions = procedures, what means that the functions will be listed as procedures.
  • Since the function pararameters are unnamed in PostgreSQL, in ISQLMetadata.GetProcedureParams() they will appear as "Arg1", "Arg2", etc. The output parameter will be named "Result".

3. Development tips

This section aims to give useful hints/tips for the dbExpress/pgExpress Driver developer.

  • Do not use TSQLQuery/TSQLTable /TSQLStoredProc.

    These classes are only included in dbExpress in order to easy migration from older BDE applications. Use always a TSQLDataset instead, or TSimpleDataset if you prefer.

  • Use lowercase object names.

    Since PostgreSQL distinguishes between upper and lowercase chars, it's much easier to work always with lowercase object names. If you create objects with quotes and non-lowercase chars such as:

    create table "Test"(a integer);
    

    , you'll always have to quote them too when working with them:

    select * from "Test";
    

    Besides, VCL/CLX might have problems acessing mixed case object names since it tends to quote object names automatically.

  • Do not use unsized VARCHAR or TEXT values.

    Unsized (i.e. having no length specifier) VARCHAR fields can length up to 4Gb in size. Since VCL/CLX do not work with unsized fields, pgExpress maps them as Memo fields, and this can lead to unwated field types, specially when they are used as the return type of functions. So, instead of:

    create function getuser(varchar) returns varchar as '
      select user
    ' language sql;
    

    or:

    create table test(name varchar);
    

    use constructs such as:

    create function getname(varchar) returns varchar(100) as '
      select user
    ' language sql;
    

    or

    create table test(name varchar(100));
    
  • Do not abuse Blob/Memo fields.

    When working with Blob/Memo fields, be careful not to waste memory, network bandwidth and loading time by loading all records at once. Such large fields could be a real load into the system and make it much slower. Activating the TDatasetProvider.Options poFetchBlobsOnDemand flag can be of help in this situation.

    Just to illustrate, let's suppose we have a table with 10.000 records, each having a blob field of around 500Kb. If we load that table at once, we'll be loading 5Gb of blobs in memory - besides the other fields. Even if it's much less then this, let's take care to not load such large datasets because they're very slow to manage (by the VCL/CLX, not by the pgExpress Driver itself).

4. Version-specific Notes

This section lists version-specific notes for the pgExpress Driver:

1. PostgreSQL v8.2+

Due to lack of VCL/CLX support, the following features are not supported by the pgExpress Driver:

  • INSERT/UPDATE/DELETE RETURNING
  • Multirow VALUES lists
  • Optional target-table alias in UPDATE/DELETE

Chapter 7. About the pgExpress Driver

1. Credits

The pgExpress Driver is 100% coded by Vita Voom Software™. We would like, however, to express our gratitude to the following people:

  • The PostgreSQL Development Team, for supplying the world with the best open-source database server, and for the source code of the libpq interface. In special, we would like to thank to Tom Lane and Bruce Momjian for their support and work.

  • Luís Filidis from Internet do Brasil for help with the web site, our logo and other related issues.
  • André Quiles, for the Vita Voom Software™ logo concept.
  • The DUnit team, for an excelent testing framework.
  • The DocBook Development Team, and all involved on it's project. This documentation is written using DocBook.

We would also like to thank the following people who helped doing the pgExpress Driver localization:

  • Daniel Schuchardt, for the German (deDE) language.
  • (Anonymous), for the Chinese (Taiwan) language.
  • Miguel Angel Alonso Cacheiro, for the Spanish (esES) language.
  • Gumundur Jn Halldrsson, for the Icelandic (isIS) language.
  • Zsolt Gombos, for the Hungarian language.
  • Jn Šuavec, for the Slovak language.
  • Petio Tonev, for the Bulgarian language.
  • Matteo Cavalleri, for the Italian language.
  • Eric Libert, for the French language.

2. Contact, Support, Bugs

You can find more info about Vita Voom Software™ and it's products on our Web site: http://www.vitavoom.com.
If want to contact us for support purposes, have questions, report bugs, introduce comments, etc. - please use the following email: support@vitavoom.com. Please read this before sending a support request.
If you want to become a beta tester, please email to support@vitavoom.com.
For comments about the Vita Voom Software™ website, please email to webmaster@vitavoom.com.

Steve Howe howe@vitavoom.com

Appendix A. FAQ and Changelog

1. F.A.Q.

1. General Questions

1.

What is the pgExpress Driver ?

The pgExpress Driver is a PostgreSQL v7.1+ dbExpress Driver for Codegear Delphi 6+/Codegear Kylix/Codegear C++ Builder 6+.

It can use all PostgreSQL field types, and is compliant to the Codegear specifications of dbExpress drivers.

Please refer to the Changelog of the pgExpress Driver for the changes history.

2.

What are the advantages of the dbExpress architeture ?

Please refer to http://community.borland.com/article/0,1410,28688,00.html.

3.

What platforms does the pgExpress Driver run on?

As of the time this is written, the pgExpress Driver was tested and runs properly under Kylix 1/2/ 3, Delphi6/ 7 and Codegear C++ Builder 6. The supported PostgreSQL servers are 7.10 to 7.31. Support for the forthcoming PostgreSQL versions will appear as they get released.

3.1.

Is there a PostgreSQL for Windows ?

PostgreSQL 7.4 is supposed to introduce a native port for Windows. You can try the free cygwin port, available at the Cygwin package at http://www.cygwin.com. You can also buy a commercially supported Cygwin based port from http://www.dbexperts.net.

2. Programming Questions

1.

My queries that use colons are not properly executed

Since the VCL/CLX parses the colons (':') as being parameters delimiters, you need to use double colons in SQL syntax. Colons are used to do typecasts as:

/*Instead of 'select typelem::int4 from pg_type;' */
            select typelem::::int4 from pg_type;

You can also use the cast() function, similary:

select cast(typelem as integer) from pg_type;

The pgExpress Suite includes proper escaping functions to work with such queries.

2.

I can't run parametrized select TSQLClientDataset queries, or my queries only work for the first parameter and don't get refreshed.

The problem is Delphi's weirdness :-) You should use a code like this:

procedure TForm1.Button1Click(Sender: TObject);
begin
with SQLClientDataSet1 do
  begin
    CommandText := 'select * from pg_type where typname ~~ :type';
    if Active then
    begin
      Params[0].AsString := Edit1.Text;
      Execute;
      Refresh
    end       
    else
    begin
      with Params.CreateParam(ftString, 'type', ptInput) do
      AsString := Edit1.Text;
      Open;
    end;
  end;
end

Obs:

The pg_type table is an internal PostgreSQL catalog table that is avaiable on all PostgreSQL databases, so it's a good table to work as example.

Now explaining it:

  1. Before calling a parametrized query, you must create a TParam for each parameter you set in the CommandText property, and assign them to the TSQLClientDataset.Params property:

    with Params.CreateParam(ftString, 'type', ptInput) do
                    AsString := Edit1.Text;
    

    Good values to use as test Paramaters are '%a%' (for matching any type that has an 'a' in its name) or 't%' (for any type that starts with 't'). Remember that '%' is PostgreSQL's wildcard char.

  2. The first time you open the query, everything hould be ok: the parameter is correctly interpreted and the query comes filtered:

    Open;
    
  3. As quoted from the Delphi's help's [TCustomClientDataSet.Params] entry, we have to set the new Param value and then call Execute at the second time:

    Warning: The parameters are only applied to the provider when a query or stored procedure is run the first time the client dataset fetches records. To change parameter values and force a query or stored procedure to be rerun with new values, use the Execute method."

    ... what lead us to...

    Params[0].AsString := Edit1.Text;
                    Execute;
    
  4. After calling Execute, we have to refresh (or close/reopen) the TSQLClientDataset so it willl match the new rows retrieved:

    Refresh;
    

3.

Using text fields as strings is very slow and uses a lot of memory.

This happens because the Delphi String field has a limited size and psql text fields have arbitrary length. Thus, pgExpress is obligated to allocate the maximum string length, which is 32k. This leads to datasets that are slow and uses more memory then what's needed most times. Unhappily, this is a dbExpress design flaw (or "misfeature"): there is no real support to variable length strings, only for fixed lengthed. Mapping those text fields as (Blob) Memo fields will be more efficient the as strings in terms of memory. If you can do it, however, we advice to change your text fields to varchar or char field types with a smaller field length; they will be more efficient in Delphi due to the more efficient memory allocation. To do this, define the TextAsMemo special param in your configuration (please follow the steps in the pgExpress Driver distribution's documentation):

TextAsMemo = True

Also you might want to define poFetchBlobsOnDemand in your TSQLClientDataset.Options property (or in your TProvider). This will fetch the blob fields only on demand, making the grids scroll much faster and using less memory.

The pgExpress Suite product circunvents this issue automatically for the string fields.

Note

TextAsMemo=True is the default behavior for the pgExpress Driver.

4.

My queries using backslashes '\' fail.

This is not a bug, but a PostgreSQL feature. The '\' is used to escape the SQL strings to allow use of chars like ''' (which is the string delimiter), '\t' (TAB), '\0' (char #0), etc - pretty much like C language or the Format() function, familiar to DelphiKylixC++ Builder/. Without this feature, it wouldn't be possible to uses such chars in SQL queries. Please refer to the link below for more information:

http://www.vitavoom.com/postgresql-docs/sql-syntax.html#SQL-SYNTAX-STRINGS

5.

I'm having problems with queries with timestamp/datetime fields.

The problem is caused by a dbExpress VCL/CLX bug. There is an interface called ISQLCursor.isSearchable() making an update query, and that would create a statement that would have a non-existent value, like this:

update test set b = '2002-08-02 18:36:50' where b = '2002-08-02 18:36:52';

Obviously PostgreSQL will not be able to find the b value from the WHERE clause, and a exception message like this will be raised:

Record not found or changed by another user

To solve this, use a primary key/index and the UpdateMode to upWhereKeyOnly mode with keys on fields that are not timestamp/ datetime/etc (do not make the timestamp values indexed). This will keep VCL/CLX from generating a wrong WHERE statement.

If in your database these fields are indexed, removing the pfInWhere option from the TField.ProviderFlags property for that field should be enough. If the actual value in your table that have no fraction or timezone value values, the generated SQL will be able to find that record (because it will use only the indexed fields in the WHERE clause, and the update will suceed.

Another way of solving this issue is by using a view using the date_trunc function, like this:

create view TestView as select a, date_trunc('second', b) as b from test;

and then create a rule to INSERT/UPDATE/DELETE rows, but this method is more complicated.

The pgExpress Suite does not suffer from this problem since it maps the fields to custom types. Just to document, the Delphi 7 Readme.txt file has a similar Known Issues note for the DB2 dbExpress driver.

6.

I want to do updates using OIDs but pgExpress does not supports it.

In fact pgExpress *does* support it, but you have to do it the right way (please read the note at the end of the answer):

select oid, * from pg_type;
  1. In your TSQLDataset component, construct your query so that it will retrieve the OID field. If you don't explicitly declare you don't want this field, psql will not return it. An example:

  2. In your TSQLDataset component, for all the TField field definitions, unset all the ProviderFlags = pfInKey, except for the OID field definition; this field has to have the pfInKey ProfiderFlag. This is because it will be our primary key.

  3. You might also want to set for the OID field definition the pfHidden flag. This means it will be used on updates for can't be seen by the client (what makes total sense with OID fields).

  4. Set TSQLDataset.UpdateMode = upWhereKeyOnly . This will make OID field the only one used to generate the WHERE statements.

  5. That's it. An alternative way would be using TSQLDataset.UpdateMode = upWhereAll, and deactivate the pfInWhere flag for all other fields.

Notes:

  • As of PostgreSQL7.2, the OID field is optional. Certify that the table you want to use for OID updates has that field before trying to use it.
  • Contrary to what most users think, OID fields are not indexed. This means the updates whose WHERE clause are based on those fields will be slow, since a sequential scan will have to be used. Thus, we don't advice using OID fields for doing the updates, unless you make an explicity index for it (yes, that is perfectly legal). Probably a standard primary key field would be much better for doing the updates.

7.

Why does pgExpress consumes so much memory ?

The pgExpress Driver itself uses very little memory. The problem is the behavior of libpq and TClientDataset: both cache the rows read from the server. Imagine the following situation: you run a query which reads 100.000 records from the server. The libpq library will cache all of them, as strings, in the memory. Additionally, the TClientDataset (remember that TSQLClientDataset and TSimpleDataset also have an internal TClientDataset component, which inherites from TCustomCachedDataset , which caches all rows read) component will be caching every record internally too. This will end up caching the rows twice. For large datatsets, this could mean lots of megabytes of memory used.

To minimize this effect, we have to reduce the memory used by the libpq library, using the BlockRead special param. The libpq library will only cache RowsetSize records, which usually is a small value (like 100). This will reduce the memory spent by libpq and have an enourmous impact on the overall memory usage.

Also, since TClientDataset caches the records in a binary format, they usually spend less memory then their string versions (as stored internally by the libpq library).

8.

Can you recommend me a good book about dbExpress ?

To develop using dbExpress can be a bit tricky sometimes, due to the amount of flexibility the technology provides, and to the new paradigm it offers. Hapifully, it's fairly easy to use dbExpress when you know how. We recommend this book for dbExpress development:

Delphi/Kylix Database Development DataCLX for Windows and Linux by Eric Harmon

Get it at:
Publisher's site
Amazon

9.

My tables float/numeric fields can't be opened; a "Catastrophic failure" message is raised.

The problem here is a incompatilibity between the decimal separator of the client system (the Delphi/Kylix/C++ Builder program) and the PostgreSQL server. Usually, the PostgreSQL uses the "C" locale, which uses '.' as decimal separator. In a few cases, the pgExpress Driver won't detect this change automatically: the pgExpress Driver will be expecting '.' as decimal separator, and not ',' as used by some locales (such as most european locales). When the pgExpress Driver tries to convert the server value (ex: '1,0') expecting a '.', an exception is raised by the VCL/CLX.

To circunvent this, you can either:

  • Use the "C" locale (or any other locale that uses '.' as decimal separator; (an easy way to do it is editing your postgresql.conf file)

  • ... or use the ServerDecimalSeparator special param to switch the decimal separator char to ',' (or '.' depending on your setup).

  • On PostgreSQL 7.4+, you might update the locale settings on the fly:

    update pg_settings set setting='C' where name='lc_numeric';
    update pg_settings set setting='C' where name='lc_monetary';
    

Note

If the pgExpress Driver can't automatically detect the decimal separator on your system, and you want to help us debugging it, please create an empty database and send us host/user/password/database information so that we can connect on your database and test it. No data will be harmed of course.

10.

Under Win95, I can't connect to some machines. I get messages like:

Connection to the database 192.x.x.x unsuccessful. Could not connect to DB Server. Reason [unknown hostname 192.x.x.x]

The libpq library needs Winsock 2 in order to sucessfully connecting to the PostgreSQL server. Please install the Winsock 2 update and everything should work.

11.

Why does my query/function return a TMemoField field instead of a TStringField on VARCHAR fields?

The query/function is returning a VARCHAR VARCHAR field without length specifier; that could be up to 4gb in size. Since the VCL/CLX does not support arbitrary length string fields, they must be mapped as Memo fields.

Fixing this situation is easy: just specify a length to those string fields:

select cast(f1, varchar(30)) from mytable;

The same behavior can occur when using functions that return variable length VARCHAR fields:

              select substr(name, 1, 10) from mytable; 
            

To get what you expect from this query, use:

              select cast(substr(name, 1, 10), varchar(10)) from mytable; 
            

12.

I'm getting "Record changed or not found" when trying to update a dataset.

This is happening because the VCL/CLX is not being able to find - or is finding more then one - record which you're trying to change. This is not a bug at all; it's instead a lack of configuration parameters. Probably you need to set a primary key in your dataset, and the generated update statement will have a WHERE clause valid for that record. The SQL generated by dbExpress is directly a related to the database primary key and the parameters set on the VCL/CLX database components.

The default TDatasetProvider Provider update setting is upWhereAll; that is rather inneficient since it will use all the fields in the dataset to compose the primary key used in the WHERE clase of the SQL statement - and it probably was not enough since the error message above is being raised. Instead, try to use upWhereKey on the TDatasetProvider and set the appropriate values on the TSQLDataset's field's ProviderFlags property to the dataset's primary key. Please read the documentation of these properties for more details.

To debug this situation and understand the exact communication between the pgExpress Driver and the PostgreSQL server, try attaching a TSQLMonitor into your TSQLCOnnection and inspect the produced log, or instead activating debug logging into the PostgreSQL server and checking it directly. The WHERE clause produced should be reflecting the properties described above.

13.

My application works under Windows XP (or others), but not under Windows 98 (or 95); it says it cant' load the libpq library.

Depending on the compiler which compiled the libpq, it could be the msvcr80.dll file instead. Try installing the msvcr71.dll library into your system, or using the which comes with the official for Windows distribution.

14.

On Delphi 2007, my boolean fields show wrong values; for instance, they are all loaded as True.

Please update your Delphi 2007 installation.

15.

Is there any way to force the pgExpress Driver to use case-sensitive object names ?

Normally this is caused to bad detabase design or to force compatibility with other database systems. PostgreSQL distinguishes between upper and lower cases when the object names are quote, e.g.:

select "typname" from pg_type;
select TYPNAME from pg_type;
          

That query will suceed while the following ones will not:

select "Typname" from pg_type;
select typname from "PG_TYPE";          

Since the VCL/CLX quotes the objects names by default, PostgreSQL will be distinguishing between them.

To avoid that, up to Delphi 7, please use the QuoteObjects (beware that uses an internal pgExpress Driver hack. On later Delphi versions, disable TDatasetProvider.Options poUseQuoteChar flag.

For a better understanding of what is running under the scenes between the pgExpress Driver and the PostgreSQL server, and check the quotes added to statements, please attach a TSQLMonitor into your TSQLConnection component and log the communication between them into a file.

16.

I think I have a bug, or I have this doubt; I need support. Could you help me ?

Of course: that's what we are here for. But to allow us to help you better, please include in your email (whenever it applies):

  • The Delphi/Kylix/Codegear C++ Builder, pgExpress Driver server (PostgreSQL's) and client (pgExpress's) OSs, PostgreSQL and libpq versions you are using.
  • If you are a registered customer, quote your registered user's name somewhere into the top of the email, such as: "Registered User Name: xxxxxxxxxxxx". Registered users always have priority support.
  • A small (as bare as possible) project that allows us to reproduce your problem. Try to set it's TSQLConnection.ConnectionName to "PGEConnection" (this is the the default test entry for the pgExpress Driver). If your project has a problem just by loading a table, this could be skipped; otherwise, please do it.
  • A pg_dump of your data/table with the '-d' option. This option will generate INSERT instead of COPY commands and will be more portable and easier to restore. All tables accessed by your project should be in the dump. You can skip this if you have a doubt/problem that is not related to some specific data, or if it can be reproduced using PostgreSQL system catalog tables.
  • Last but not less, a good description of your problem and the things you tried to solve it, if any. Please describe how we can reproduce your situation in order to allow us to fix/help you.

Obviously any data sent us remain private and be used solely for testing purposes and will be deleted as soon as your support request is considered done. Also, remember that the easiest to reproduce your problem, the easier for us to help you.

2. Changelog

This section lists changes history of the pgExpress Driver.

If you have doubts or need support, please write us at support@vitavoom.com.

Version 4.50 - Release Date: 27 Mar 2012
New release.
ADDED

Support for PostgreSQL 9.1.

Version 4.40 - Release Date: 02 Oct 2010
New release.
ADDED

Support for PostgreSQL 9.0.

Version 4.31 - Release Date: 08 Jan 2010
New release.
ADDED

Support for PostgreSQL 8.4.

Version 4.30 - Release Date: 22 Oct 2008
Bugfix release.
ADDED

Support for PostgreSQL's 8.3 UUID fields.

ADDED

Documentation enhancements.

ADDED

Enhanced multithreading functionality.

CHANGED

OID fields will always be mapped as int4. Please check OID type for details.

FIXED

Fixed GetProcedureParams() interface, what fixes store procedures usage under IDE.

FIXED

Fixed RoleName parameter under protocol 4.0 (Delphi 2007+).

FIXED

Fixed timestamp millisecond bug.

Version 4.23 - Release Date: 07 May 2008
Bugfix release.
FIXED

Small bugfixes.

Version 4.22 - Release Date: 01 Apr 2008
Bugfix release.
FIXED

Fixed access violations in some particular situations.

FIXED

Fixed issues with timestamp fields under Delphi 2007.

Version 4.21 - Release Date: 23 Mar 2008
Bugfix release.
FIXED

Fixed random memory error / "Read of address FEEEFEEE in module 'libpq.dll'" messages.

Version 4.20 - Release Date: 06 Feb 2008
New major version.
ADDED

PostgreSQL 8.3 support. XML fields will be mapped the same way TEXT fields are, i.e. as Blob/Memo; Section 4, “Types Mappping” for details.

ADDED

Enhanced Delphi 2007+ support (dbExpress 4 support). Please see Installation on dbExpress 4.0 protocol (Delphi 2007+) for details. With that feature comes also new DBX4Compatible special param.

ADDED

Now the pgExpress Driver can generate large log messages (> 1024 bytes) (log messages can be captured by TSQLMonitor instances).

ADDED

Documentation enhancements.

FIXED

pgExpress won't refuse to work with 8.2.6 (or later) versions anymore.

Version 4.11 - Release Date: 04 Apr 2007
Bugfix release.
ADDED

Documentation enhancements.

FIXED

Fixed size of GRAPHIC blobs

FIXED

Fixed PostgreSQL's version rounding bug caused by a RoundTo() bug.

Version 4.10 - Release Date: 06 Dec 2006
Maintenance release.
ADDED

Preliminar PostgreSQL v8.2 support. Please read the version-specific notes.

FIXED

Fixed a couple OUT parameters Stored Procedures problems.

FIXED

Fixed a problem in the GetProcedureParams interface.

FIXED

Documentation fixes.

Version 4.05 - Release Date: 16 Oct 2006
Maintenance release.
ADDED

Documentation enhancements.

FIXED

Fixed a bug retrieving Stored Procedure names.

FIXED

Fixed escaped characters in memo fields.

FIXED

Fixed include in pgeDriverUtils.pas.

FIXED

Fixed numeric without precision/scale, such as:

create table test(a numeric));
FIXED

Fixed some bugs on the automatic Fetch Cursors interfaces

Version 4.04 - Release Date: 01 Jun 2006
Maintenance release.
ADDED

Support for the EnterpriseDB.

FIXED

Int8Mode could be ignored on certain systems.

Version 4.03 - Release Date: 25 Apr 2006
Bugfix release.
ADDED

Documentation enhancements.

FIXED

Fixed a bug on Memo fields with protocol 3.0 drivers (garbage at the end of the field).

FIXED

Fixed a problem with stored procedure parameters introduced on the 4.x series.

FIXED

Fixed a problem with empty string parameters under Kylix.

FIXED

Added a workaorund for a PostgreSQL parser bug where floats are not recognized if not quoted (ex: update mytable where myfloat = 1.00)

FIXED

Some small bugfixes.

Version 4.02 - Release Date: 06 Mar 2006
Bugfix release.
ADDED

Added support for the VCL/CLX "Trim Char" parameter.

FIXED

Fixed a bug with string parameters on protocol v3.0 drivers.

FIXED

Fixed a bug on virtual cursor interfaces that could cause problems on the GetColumnNames() interface in and stored procedures.

FIXED

Fixed a bug with blob (bytea) parameters.

Version 4.01 - Release Date: 27 Jan 2006
Bugfix release.
FIXED

Fixed a couple bugs in the 4.00 version.

Version 4.00 - Release Date: 26 Jan 2006
New major version: BDS 2006 and UNICODE support.
ADDED

Added BDS 2006 compatibility. This includes support for protocol v3.0, unicode interfaces, native int64, enhanced dbExpress API. pgExpress is the first driver to add such support.

ADDED

Enhanced UNICODE support. Check also the UnicodeAsWideChar parameter. If you have problems opening bases with UNICODE encoding, add a client encoding to your dbxconnections(.ini) entry, such as:

ServerCharset = /latin1

For more details, please refer to Section 1, “Multibyte, UNICODE and Locales”.

ADDED

With the introduction of protocol 3.0 support in BDS 2006, now we have two new drivers, dbexpge30.dll and dbexpge30-ml.dll, whose implement it. These drivers will work only on BDS 2006 and later. The regular pgExpress Driver which implements dbExpress protocol 2.5 still works with BDS 2006, but pgExpress protocol 3.0 won't work with applications built for older protocol implementations.

ADDED

Added UnicodeAsWideChar special param: will map char/varchar fields as TWideString fields. This will work only if the client encoding is UNICODE, and with protocol 3.0 or above.

ADDED

Added BorlandCompatible special param, which adds more compatility between pgExpress and Codegear drivers, on the NUMERIC mapping.

ADDED

Documentation enhancements.

ADDED

The following new interfaces are supported:

  • eConnConnectionString
  • eConnPrepareSQL
  • eConnDecimalSeparator
  • eConnEncrypted
  • eConnMultipleTransaction
  • eCommCursorName

Most of these interfaces will only be recognized on BDS 2006 please check your IDE documentation for more details.

ADDED

The libpq library was updated to version 8.1.2, for both Linux and Windows.

CHANGED

Now if the client encoding is UNICODE and the application does not support that encoding (all compiled with compilers before BDS 2006), or do not user UnicodeAsWideChar, the pgExpress Driver will automatically set the client encoding to LATIN-1. While it should fit most users, it can be easily changed to any desired encoding value by using the ServerCharset parameter.

FIXED

Fixed a bug where the ByteaMode Special Param would not be recognized on all situations.

FIXED

Fixed libpq dependencies on comerr32.dll and other external libraries.

FIXED

Fixed libpq loading under Win9X.

FIXED

Fixed a licence bug on Windows.

Note

Older versions information has been ommited to keep this document cleaner.