I’m in the process of migrating from an older version of PostgreSQL to a newer version. I’d like to see what the differences are between the configuration (${PG_DATA}/postgresql.conf) of both servers. I couldn’t find an easy, ready-made solution, so I hacked up one using plain old SQL, which turns out to be particularly well suited to comparing sets of data :)

First, get the settings from the old server. We’ll use psql to execute the SHOW ALL query and pipe the result (stripped of all extraneous formatting) to the file old_settings.txt. (I’m using the long versions of the command flags, as well as adding in lots of newlines, to aid in readability and comprehensibility.)

psql --username postgres \
     --dbname postgres \
     --host OLD_SERVER_ADDRESS \
     --port OLD_SERVER_PORT \
     --output old_settings.txt \
     --no-align \
     --quiet \
     --tuples-only \
     --command 'show all'

Now, we’ll need the settings from the new server. We use the same trick, but pipe the output to the new_settings.txt file, instead.

psql --username postgres \
     --dbname postgres \
     --host NEW_SERVER_ADDRESS \
     --port NEW_SERVER_PORT \
     --output new_settings.txt \
     --no-align \
     --quiet \
     --tuples-only \
     --command 'show all'

So now we have the data in a format that is easily loaded into a PostgreSQL database! On some other database, we create some simple tables to hold the information; their format is that of the output of the SHOW ALL command.

CREATE TABLE old_server(parameter TEXT, value TEXT, description TEXT);
CREATE TABLE new_server(parameter TEXT, value TEXT, description TEXT);

Now copy the information into the tables using the \copy command:

\copy old_server from ./old_settings.txt delimiter as '|'
\copy new_server from ./new_settings.txt delimiter as '|'

We’ll create a view to massage this data into a nice report in order to more easily see what’s different:

CREATE VIEW configurations AS
    older.value as original_value,
    newer.value AS current_value,
    (older.value != newer.value) AS "different?",
    (newer.parameter IS NULL) AS "removed?",
    (older.parameter IS NULL) AS "new?"
FROM new_server AS newer
LEFT JOIN old_server AS older  -- there might be some parameters that are no longer there
    ON newer.parameter = older.parameter

Finally, we can execute some simple queries on this view to show us what’s going on:

-- What parameters are different?
SELECT parameter, original_value, current_value FROM configurations WHERE "different?";

-- What are the values of the parameters that are not present in the original configuration?
SELECT parameter, current_value FROM configurations WHERE "new?";

-- What are the values of the parameters that have been removed since the original database version?
SELECT parameter, original_value FROM configurations WHERE "removed?";

Problem solved!