Search code examples
postgresqlpostgresql-9.2pg-restore

pg_restore is not disabling triggers


Using PostgreSQL 9.2.8, I'm trying to restore just my data from one database into another but the triggers seem to still be running. I've written the script, shown below, to do the copy.

Basically I have dts as my production database, and I have DigitalTrafficSystem as my development database. The table structures are the same, but the dev one has very different stored procedures.

When the restore runs, the DigitalTrafficSystem database ends up with a bunch of extra table rows that don't exist in the dts database, so I'm assuming those are getting created by triggers.

The messages I get related to triggers, for each table, look like so:

pg_restore: [archiver (db)] could not execute query: ERROR:  permission denied: "RI_ConstraintTrigger_c_136691" is a system trigger
Command was: ALTER TABLE usage ENABLE TRIGGER ALL;

I'm assuming (wrongly?) that the triggers are off, but just that system level trigger couldn't get disabled.

Here's my script:

#!/bin/sh

PGUSER=dts
FILE=/tmp/.dts.db.$$

# Dump the schema of the DB as we want this to keep
pg_dump -s DigitalTrafficSystem -f $FILE

dropdb -U _postgres DigitalTrafficSystem
if [ $? -ne 0 ]; then
    exit;
fi

createdb -U _postgres -O dts DigitalTrafficSystem
if [ $? -ne 0 ]; then
    exit;
fi

# Restore the schema
psql -d DigitalTrafficSystem -f $FILE

# Dump the data of the real production database
pg_dump -Fc -a dts -f $FILE > /dev/null
if [ $? -ne 0 ]; then
    exit;
fi

# Restore only the data from the real database to our development one
pg_restore -a -d DigitalTrafficSystem --disable-triggers -S dts $FILE

rm $FILE

Solution

  • I'm assuming (wrongly?) that the triggers are off, but just that system level trigger couldn't get disabled.

    No, because the success of an SQL command is an all-or-nothing matter. The command that fails is presumably of the form:

    ALTER TABLE usage DISABLE TRIGGER ALL;
    

    and should it fail, it will fail entirely, as opposed to doing half the job, which would be disabling the user-level trigger and leaving the RI-constraints triggers enabled.

    pg_restore doc says:

          Presently, the commands emitted for --disable-triggers must be done
          as superuser. So you should also specify a superuser name with -S
          or, preferably, run pg_restore as a PostgreSQL superuser.
    

    and

       -S username, --superuser=username
           Specify the superuser user name to use when disabling triggers.
           This is relevant only if --disable-triggers is used.
    

    But your dts is not superuser. It seems that _postgres is a superuser, according to the rest of the script. In that case, why not pass it to -S ?

    Another point is, like @wildplasser notes in comments, it's a bit weird to be bothered by triggers in a brand new database, since your script creates a database and immediately runs a data-only import. Can we assume that it's the template1 database that contain these objects, with these triggers? But then, note that the data in the tables from template1 are imported as well into the newly created database, so they must also be taken into account for any additional row found between the source of the dump and the final result in the destination database.