48

I have this Trigger in Postgresql that I can't just get to work (does nothing). For understanding, there's how I defined it:

CREATE TABLE documents (
    ...
    modification_time timestamp with time zone DEFAULT now()
);

CREATE FUNCTION documents_update_mod_time() RETURNS trigger
AS $$
    begin
    new.modification_time := now();
    return new;
    end
$$
    LANGUAGE plpgsql;

CREATE TRIGGER documents_modification_time
    BEFORE INSERT OR UPDATE ON documents
    FOR EACH ROW
    EXECUTE PROCEDURE documents_update_mod_time();

Now to make it a bit more interesting.. How do you debug triggers?

1

3 Answers 3

90
  1. Use the following code within a trigger function, then watch the 'messages' tab in pgAdmin3 or the output in psql:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;       -- either this
    RAISE EXCEPTION 'failed';  -- or that
    
  2. To see which triggers actually get called, how many times etc, the following statement is the life-saver of choice:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers
    

    Note that if your trigger is not getting called and you use inheritance, it may be that you've only defined a trigger on the parent table, whereas triggers are not inherited by child tables automatically.

  3. To step through the function, you can use the debugger built into pgAdmin3, which on Windows is enabled by default; all you have to do is execute the code found in ...\8.3\share\contrib\pldbgapi.sql against the database you're debugging, restart pgAdmin3, right-click your trigger function, hit 'Set Breakpoint', and then execute a statement that would cause the trigger to fire, such as the UPDATE statement above.

2
  • Not sure if this is how to do it on other platforms. Also I would've shared the third method earlier (it's really handy!) but I found this out a week after this question was originally posted.
    – Kev
    Commented Jan 9, 2009 at 22:57
  • 1
    Tried with Postgres 9.2 and accompanying pgAdmin. There no Set Breakpoint menu anywhere even after following the instructions mentioned above. Also the file is located at ...\9.2\share\extension\pldbgapi-1.0.sql. OS: Windows Server 2008
    – Dojo
    Commented Jan 1, 2016 at 10:15
12

Turns out I was using inheritance in the above problem and forgot to mention it. Now for everybody who might run into this as well, here's some debugging hints:

Use the following code to debug what a trigger is doing:

RAISE NOTICE 'test';       -- either this
RAISE EXCEPTION 'failed';  -- or that

To see which triggers actually get called, how many times etc, the following statement is the life-saver of choice:

EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers

Then there's the one thing I didn't know before: triggers only fire when updating the exact table they're defined on. If you use inheritance, you MUST define them on the child tables as well!

1
4

You can use 'raise notice' statements inside your trigger function to debug it. To debug the trigger not being called at all is another story.

If you add a 'raise exception' inside your trigger function, can you still do inserts/updates?

Also, if your update test occurs in the same transaction as your insert test, now() will be the same (since it's only calculated once per transaction) and therefore the update won't seem to do anything. If that's the case, either do them in separate transactions, or if this is a unit test and you can't do that, use clock_timestamp().

I have a unit test that depends on some time going by between transactions, so at the beginning of the unit test I have something like:

ALTER TABLE documents
   ALTER COLUMN modification_time SET DEFAULT clock_timestamp();

Then in the trigger, use "set modification_time = default".

So normally it doesn't do the extra calculation, but during a unit test this allows me to do inserts with pg_sleep in between to simulate time passing and actually have that be reflected in the data.

7
  • Good hint... so it appears the function doesn't get called.. any idea why?
    – Dave Vogt
    Commented Nov 20, 2008 at 19:28
  • Do you have execute permissions on the trigger function?
    – Kev
    Commented Nov 20, 2008 at 19:45
  • You may want to fully qualify (prepend the schema name) the names of the various objects, just to be on the safe side. Also you probably could leave out the "INSERT" part of your trigger definition, the default value takes care of this case. Commented Nov 20, 2008 at 20:02
  • think so.. I created it! re-granting also didn't help :(
    – Dave Vogt
    Commented Nov 20, 2008 at 20:05
  • Maybe you could provide your test inserts/updates? Was the transaction thing relevant at all?
    – Kev
    Commented Nov 20, 2008 at 21:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.