How do I edit a trigger function? - postgresql

How would I edit a trigger function in postgresql using psql? I have tried the using \ef trigger_name and every single time I try that it does not stick. Do I have to drop all of the triggers that refer to that trigger function before attempting to update it? I have been looking at the docs for a while and I did not find anything saying that I must to that? I have tried typing in the CREATE OR REPLACE... by hand into psql and that did not work.

Related

Postgresql - Unable to find source code for function called by trigger

I have a trigger that runs on insert or update of a table but for the life of me, I can't find the source for that function... where should I be looking?
The SQL for the trigger:
CREATE TRIGGER my_trigger
BEFORE INSERT OR UPDATE OF search_data
ON public.mytable
FOR EACH ROW
EXECUTE FUNCTION tsvector_update_trigger('search_vector', 'pg_catalog.english', 'search_data');
How do I get the source for the tsvector_update_trigger function? I'm looking in pgadmin right now and can't seem to find it but can also use psql.
Any help appreciated!

Use a postgres extension as a non-privileged user

The Problem
I have the following trigger function that uses the moddatetime extension:
/* BEFORE UPDATE trigger - Updates "entity_version.updated_on", setting it to the current UTC time. */
CREATE EXTENSION IF NOT EXISTS moddatetime; -- Needs superuser privileges!
DROP TRIGGER IF EXISTS trig_entity_version_before_update
ON entity_version;
CREATE TRIGGER trig_entity_version_before_update
BEFORE UPDATE
ON entity_version
FOR EACH ROW EXECUTE PROCEDURE moddatetime(updated_on); -- updated_on is TIMESTAMP type
The trigger works perfectly fine, but the issue is that the first line (CREATE EXTENSION) requires super-user privileges. Since these databases are going to be created by users (via a script) I don't want them the user that makes these databases and triggers to have super user access.
What I've tried
As a first step, running the script as a super user works fine, as you'd expect.
Naturally, the next step would be to separate the creation of the extension as a superuser from the trigger creation script. But doing that, if I run the above script without CREATE EXTENSION line, I get the following error:
function moddatetime() does not exist
Which I suppose makes sense given that the script never declares moddatetime, but I cannot find anywhere in the documentation how to define the extension as available without using CREATE EXTENSION. Surely there must be a way to import or use an extension without having the create it? Something akin to:
USING EXTENSION moddatetime; -- Does something like this exist?
... rest of the trigger script ...
You need the extension installed if you want to use it.
PostgreSQL v13 introduces the notion of a trusted extension, which can be installed by non-superusers with the CREATE privilege on the database, but this extension is not among them. So upgrading won't fix the problem.
You could connect to template1 as superuser and create the extension there. Then it would automatically be present in all newly created databases.
But frankly, I don't see the point. You can do the same thing with a regular PL/pgSQL trigger – only the performance wouldn't be as good.
As per #laurenz-albe his suggestion, I've just stepped off of using the extension for this particular use-case. Fortunately, writing a function to do what the extension does is relatively trivial. I'll include it here for reference in case someone is looking specifically to replace moddatetime.
DROP FUNCTION IF EXISTS fn_entity_version_before_update() CASCADE;
CREATE FUNCTION fn_entity_version_before_update() RETURNS TRIGGER LANGUAGE PLPGSQL AS
$fn_body$
BEGIN
NEW.updated_on = NOW() AT TIME ZONE 'utc';
RETURN NEW;
END;
$fn_body$;
DROP TRIGGER IF EXISTS trig_entity_version_before_update
ON entity_version;
CREATE TRIGGER trig_entity_version_before_update
BEFORE UPDATE
ON entity_version
FOR EACH ROW EXECUTE PROCEDURE fn_entity_version_before_update();

PostgreSql Event trigger for Auditing

I am about to implement an audit system in my database and am looking for the most effective way to do this.
I've read the wiki and did my research.
There is this example: https://wiki.postgresql.org/wiki/Audit_trigger
And also this: https://wiki.postgresql.org/wiki/Audit_trigger_91plus
In the listed examples you have to create a trigger for each table (kinda redudant).
However with Postgres 9.3+ we have the ability of event triggers where we can react on special events like create, alter or drop table.
An optimal solution would be:
create event trigger UpdateTables
on ddl_command_end
when tag in ( 'insert ', 'update ')
execute procedure DoAudit();
However that returns:
ERROR: filter value "insert " not recognized for filter variable "tag"
SQL Status:42601
I am wondering if we also can react on insert, update events with event triggers and use this single trigger for all auditing?
This won't work.
The "on ddl_command_end" means the event is intended to be invoked on structural changes in the database. The complete reference to events is here: https://www.postgresql.org/docs/current/static/event-trigger-matrix.html
Have a look at this:
https://eager.io/blog/audit-postgres/
This is a quite simple, yet effective way to implement an auditing system, making use of the hstore data type. I recently tried it and it worked flawlessly "out of the box".

Learning about DB2 triggers

Hi I am trying to figure out the syntax for triggers. I have two tables one called tagged_in and the other notification. So I want to make a trigger where when an insert is called in tagged_in I want to insert a tuple in notification.
The manuals are available at the DB2 InfoCenter. Did you read the CREATE TRIGGER statement information yet? If not, why not? If so, what did you try, and what error did you get?
Something like this
CREATE TRIGGER TEST_TRIGGER
AFTER INSERT ON TAGGED_IN
REFERENCING NEW AS NEW_TAG
FOR EACH ROW
BEGIN ATOMIC
INSERT INTO NOTIFICATION
VALUES (NEW_TAG.FIELD1,NEW_TAG.FIELD2);
END

postgres trigger creation

How do I only create a trigger if it does not exist?
When I do create or replace, I get a syntax error so I am looking for a way to test for the existence of a trigger.
I can always select * from pg_trigger, but I am sure there is a more suitable way.
Thanks
Postgres can conditionally drop a trigger - see the docs. Do this before creating the trigger, then it will always work.
DROP TRIGGER IF EXISTS mytrigger ON mytable;
As Jack points out in the comments, this feature has only been available since 8.2; this has been out for more than four years though, so it should be available in your version.
CREATE TRIGGER (NameOfTrigger) AFTER INSERT OR UPDATE ON (NameOfTable)
DROP TRIGGER IF EXISTS (NameOfTrigger) ON (NameOfTable);