Category: PostgresDAC

Dump and restore of PostgreSQL: version compatibility FAQ

Compress PostgreSQLMany newbies are confused about how PostgreSQL dump and restore work. And even more questions appeared about version mismatches of the server itself and tools used. After fresh PostgresDAC release we’ve faced with the same questions.

Utilities used for dump and restore are called pg_dump and pg_restore respectively. Delphi developers may use TPSQLDump and TPSQLRestore components which are fully compatible with native tools.

So here I’m trying to create some kind of a FAQ.

Let’s assume version is a concatenation of Major, Minor and Build numbers separated by dots, e.g. 9.3.2

Q: Can I downgrade the database version, e.g. from 9.3 to 8.4?
A: If you mean official supported way of doing this, then no, you can’t. You may however use pg_dump in plain text output mode and manually fix all incompatibilities.

Q: Can I create dump of old server with new pg_dump?
A: Yes, sure. All versions since 7.0 are supported now. But if you use custom format, be ready the same or higher version of pg_restore will be needed.

Q: Can I create dump of new server with old pg_dump?
A: pg_dump must have the same major and minor version or higher, e.g. pg_dump v9.2.3 will work on v9.2.5, 9.2.x, 9.1.x, 8.x etc. and will not work for versions like 9.3.x, 9.4.x etc.

Q: What if I want to restore custom dump archive to the old server anyway?
A: You should use pg_restore to generate plain SQL script, manually edit it to fix version mismatches.

Q: Will pg_restore “understand” archives of newer versions of pg_dump?
A: No. The rule is simple: pg_restore will work with pg_dump output of the same major and minor version or lower, e.g. pg_restore v9.3.x will understand pg_dump output v9.3.x, 9.2.x, 9.1.x, 8.x etc. and will not work with output from versions like 9.4.x.

Q: Can I use new output format of the pg_dump with old server version, e.g. directory output for 8.4 server?
A: Yes, you can.

Q: Can I use new parallel functionality with old servers?
A: Yes, you can, but there is a limitation for pre-9.2 servers. See description for –no-synchronized-snapshots parameter.

PS All these statements are correct for the PostgresDAC’s TPSQLDump and TPSQLRestore components.

Development using Lazarus and PostgresDAC. Installation


There are a lot of tools for PostgreSQL development. I want to propose you one more. Why Lazarus:

  • Lazarus is shipped with open-source Pascal compiler;
  • it has a high degree of Delphi compatibility;
  • availability on a variety of platforms, including Windows, Mac OS X, and Linux;
  • complete source code is available;

Installing Lazarus

Go to Lazarus at SourceForge.

Then at the Downloads Section get proper installer. I used lazarus-1.0.8-fpc-2.6.2-win32.exe and lazarus-1.0.8-fpc-2.6.2-win64.exe in my tests. These are the latest releases at the moment.

Here are the screen shots of the installation process where you can see what I had chosen:
Lazarus Installation

Path to install

Full installation

I have Lazarus installed into C:\lazarus\ and hereafter I will use this path.

Getting PostgresDAC

Now it’s time for PostgresDAC. At the moment many Laarus IDE functions require the source and warns if the source of a unit is missing. Thus we need PostgresDAC with sources version. Sources are available for licensed users in their profile.

MicroOLAP Profile

I have extracted PostgresDAC sources to C:\PostgresDAC\.

Install PostgresDAC into the IDE

In the Lazarus IDE choose open package and select dclPostgresDACL.lpk. This is the design time package. Then in the Package window choose Use → Install.
Install package

Confirmation about rebuild will appear.


Choose “Yes”. Wait for some time. After successful rebuild Lazarus will reopen itself. Tada! We got it!

PostgresDAC in the Lazarus

Now we may open some demo projects and play some time.
GridDemo for PostgresDAC in the Lazarus

Number into words convertion in PostgreSQL

I was playing with some unit tests for PostgresDAC recently. And one test case was to check TPSQLDataset.Locate routine which allows partial-string and case-sensitive matching options. So I want to have some test result set with integer and text columns. The simplest for me are numbers in both representations: using digits and using words, e.g.

  1. one
  2. two
  3. three
  4. four
  5. etc.

Since I hadn’t much spare time I used nice VALUES command:

VALUES (1, 'one'), (2, 'two'), (3, 'three');

Considering I needed special names for columns I used more complex query:

SELECT col1, col2::varchar(10) FROM 
(VALUES (1, 'one'), (2, 'two'), (3, 'three')) AS t(col1, col2);

I did my task well. However I was wondering is there any built-in function in PostgreSQL which may convert integer to such words representation. The answer is: not exactly.

I found some references to cash_words function. But there is no any information (except entry in 7.3 release notes) in the official documents. The use case is quite simple:

SELECT cash_words(gen.i::money) FROM generate_series(1, 10) AS gen(i);
cash_words text

"One dollar and zero cents" "Two dollars and zero cents" "Three dollars and zero cents" "Four dollars and zero cents" "Five dollars and zero cents" "Six dollars and zero cents" "Seven dollars and zero cents" "Eight dollars and zero cents" "Nine dollars and zero cents" "Ten dollars and zero cents"

I’m fine with this result set, who needs only numbers may trim values using standard functions.

PS In case someone wants to create his own implementation using C (or plpgsql, who knows), cash_words function may be found in the \src\backend\utils\adt\cash.c file. It uses num_word private routine.

The tale of how PostgresDAC became the cross-platform component suite

As some probably know Delphi XE2 now have compilers for Win32, Win64, Mac and iOS. And as you probably guessed, we were inundated with questions from our customers about support for this zoo in our DACs.

Frankly speaking this situation is perfectly described in Joel’s Spolsky “Fire and motion”. We thought: “This just can’t be done in a sane time!”

However “you never know what you can do till you try” and “the devil is not so black as he is painted”. So we decided to port PostgresDAC first. The main reason was the using of libpq.dll client library, which may be built for a huge amount of target platforms.

Thus we don’t need to worry about low-level network routines and may pay the whole of the attention to the middle layer, have no idea how to name it.

As for Win64 platform, then were no problems at all. We’ve prepared x64 deploy libraries and we done with it. There were no dangerous places in our source code were address arithmetics may produce unsuspected behavior. This simplicity is understandable. We just stayed within one Windows platform in general.

Then it was Mac’s turn. When we started I have never seen MacOS before… That was scary move. Especially for my self-esteem. :)

We crossed the fingers, chose OS X as the target platform and the fun began. I knew our code was Windows-centric, but I was so far from the real understanding of the scope of the tragedy. :)

Here is the seven deadly sins for the cross-platform library written in Delphi:

1. Using of Windows unit is prohibited. The only things you have are System ans SysUtils. Deal with it!

2. Using of VCL units (Controls, StdVCL, ExtCtrls etc) is prohibited. There’s no VCL on Mac, FireMonkey only.

3. Using of forms is prohibited. So no custom dialogs, message boxes etc. You have no idea under which platform library is built. Well, this is so true for console application too. That’s why we’ve removed annoying trial screen.

4. Ignoring compiler directives is stupid. Remember the first sin? Yeah, sometimes you’ll need low-level OS’s functionality. If so, do it smart:

Posix.SysTypes, Posix.Stdio, Posix.Stdlib

5. Using of messages, window procedures, handles, file mappings and other Win-shit is prohibited. That’s why our TPSQLMonitor is still useless for Mac. We need to rewrite it from scratch. And we ready for it.

6. Use correct type naming, e.g. LongWord instead of DWORD.

7. Use proper functions or implement them for all platforms. No place for ZeroMemory, CopyMemory, GetTickCount on Mac etc.

You know, when I wrote the number of seven I didn’t think that I’m so damn write! Of course in your case there may be dozen of others incompatibilities. That was just a joke. :)

Holiday discounts on pgmdd & postgresdac

Ded MorozHolidays came suddenly. I know we’re little bit late with Christmas presents, but who cares anyway!

Everybody is welcome to use “Christmas” coupon code till January 14 for 20% discount on any product from MicroOLAP Technologies including the most robust Database Designer for PostgreSQL and PostgresDAC component suite.

From all of us at MicroOLAP, we wish you happy holidays and a prosperous new year!

Delete tuple from libpq’s PGresult

I wrote how to modify result set in underlying libpq’s PGresult object with new ones.

But there was no solution for deletion. Here I want to propose one solution. The main idea is to copy existing PGresult content to the new record except deleted tuple. For this we will use PQcopyResult function. Delphi code looks like this:

  CurrentRecNum: LongInt;
  DeletedRecNum: LongInt;
  ATempCopyStmt: PGResult;
  fval: PAnsiChar;
  flen, i, j: integer;

     //FStatement - is our active result set
     ATempCopyStmt := PQcopyResult(FStatement, PG_COPYRES_ATTRS);
     if not Assigned(ATempCopyStmt) then
       raise Exception.Create('Cannot copy results');
     j := 0;
     for CurrentRecNum := 0 to PQntuples(FStatement) - 1 do
       if CurrentRecNum = DeletedRecNum then 
          Continue; //exclude row from new set
       for i := 0 to PQnfields(FStatement) - 1 do
           fval := PQgetvalue(FStatement, j, i);
           flen := PQgetlength(FStatement, j, i);
           if PQsetvalue(ATempCopyStmt, j, i, fval, flen) = 0 then
             raise Exception.Create('Refresh for deleted fiels failed');
     PQclear(FStatement); //clear old result set 
     FStatement := ATempCopyStmt; //switch to the new