Checking if the trigger exists before executing a query - triggers

I want before executing the following query
alter trigger my_trigger disable
check if the trigger exists or not
How can I check if the trigger exits ? (RDBMS: oracle)

You could do something like this:
select * from sys.triggers where name = 'My_Trigger'
Querying Information_Schema would be ideal, but I'm not sure trigger information can be found there.

Related

PostgreSQL - Trigger Each Statement - How to get Query statement

I'm doing a trigger Each Statement and I would like to access the Query Statement that triggered the trigger. Is this possible ?
Something like this:
update table_1 where id> 300;
This query triggers an update event in table table_1 and this event triggers a function associated with the update trigger. This trigger is configured as Each Statement and inside the trigger I would like to do something like this:
raise info 'Query Statement that fired this trigger:%', last_query();
Would this be possible?
Thank you!
Julio
Call the function current_query().

Postgresql ignoring 'when' condition on trigger

A trigger seems to be ignoring the 'when condition' in my definition but I'm unsure why. I'm running the following:
create trigger trigger_update_candidate_location
after update on candidates
for each row
when (
OLD.address1 is distinct from NEW.address1
or
OLD.address2 is distinct from NEW.address2
or
OLD.city is distinct from NEW.city
or
OLD.state is distinct from NEW.state
or
OLD.zip is distinct from NEW.zip
or
OLD.country is distinct from NEW.country
)
execute procedure entities.tf_update_candidate_location();
But when I check back in on it, I get the following:
-- auto-generated definition
create trigger trigger_update_candidate_location
after update
on candidates
for each row
execute procedure tf_update_candidate_location();
This is problematic because the procedure I call ends up doing an update on the same table for different columns (lat/lng). Since the 'when' condition is ignored this crates an infinite loop.
My intention is to watch for address change, do a lookup on another table to get lat/lng values.
Postgresql version: 10.6
IDE: DataGrip 2018.1.3
How exactly do you create and "check back"? With datagrip?
The WHEN condition was added with Postgres 9.0. Some old (or poor) clients may be outdated. To be sure, check in pgsql with:
SELECT pg_get_triggerdef(oid, true)
FROM pg_trigger
WHERE tgrelid = 'candidates'::regclass -- schema-qualify name to be sure
AND NOT tgisinternal;
Any actual WHEN qualification is stored in internal format in pg_trigger.tgqual, btw. Details in the manual here.
Also what's your current search_path and what's the schema of table candidates?
It stands out that the table candidates is unqualified, while the trigger function entities.tf_update_candidate_location() has a schema-qualification ... You are not confusing tables of the same name in different DB schemas, are you?
Aside, you can simplify with this shorter, equivalent syntax:
create trigger trigger_update_candidate_location
after update on candidates -- schema-qualify??
for each row
when (
(OLD.address1, OLD.address2, OLD.city, OLD.state, OLD.zip, OLD.country)
IS DISTINCT FROM
(NEW.address1, NEW.address2, NEW.city, NEW.state, NEW.zip, NEW.country)
)
execute procedure entities.tf_update_candidate_location();
Unfortunately, that's the issue of DataGrip. Please follow the ticket to be notified when it's fixed.
https://youtrack.jetbrains.com/issue/DBE-7247

PostgreSQL: Creating a Trigger that tries to do work on a non existing table

as we start to migrate our Application from using Oracle to PostgreSQL we ran into the following problem:
A lot of our Oracle scripts create triggers that work on Oracle specific tables which dont exist in PostgreSQL. When running these scripts on the PG database they will not throw an error.
Only when the trigger is triggered an error is thrown.
Example code:
-- Invalid query under PostgreSQL
select * from v$mystat;
-- Create a view with the invalid query does not work (as expected)
create or replace view Invalid_View as
select * from v$mystat;
-- Create a test table
create table aaa_test_table (test timestamp);
-- Create a trigger with the invalid query does(!) work (not as expected)
create or replace trigger Invalid_Trigger
before insert
on aaa_test_table
begin
select * from v$mystat;
end;
-- Insert fails if the trigger exists
insert into aaa_test_table (test) values(sysdate);
-- Select from the test table
select * from aaa_test_table
order by test desc;
Is there a way to change this behavior to throw an error on trigger creation instead?
Kind Regards,
Hammerfels
Edit:
I was made aware, that we actually dont use basic PostgreSQL but EDB instead.
That would probably explain why the syntax for create trigger seems wrong.
I'm sorry for the confusion.
It will trigger an error, unless you have configured Postgres to postpone validation when creating functions.
Try issuing this before creating the trigger:
set check_function_bodies = on;
Creating the trigger should show
ERROR: syntax error at or near "trigger"
LINE 1: create or replace trigger Invalid_Trigger

What lock, if any, does 'CREATE TRIGGER' use in PostgreSQL 9.4.2

according to postgres-xl, CREATE TRIGGER uses the SHARE ROW EXCLUSIVE lock, but according to the official Postgres docs for SHARE ROW EXCLUSIVE:
This lock mode is not automatically acquired by any PostgreSQL
command.
You're comparing Postgres-XL with the main PostgreSQL documentation. Two different products, albeit with a shared history. Postgres-XL has lots of changes from stock PostgreSQL.
CREATE TRIGGER should be listed in the Pg docs and isn't, though, and that's an oversight.
A quick look at the source code shows that CREATE TRIGGER takes a ShareRowExclusiveLock, so in this case XL's documentation matches PostgreSQL's behaviour.
You could check this yourself without looking at the sources by doing something like this:
CREATE TABLE test();
CREATE OR REPLACE FUNCTION dummy_tg() RETURNS TRIGGER
LANGUAGE plpgsql AS $$ BEGIN END; $$;
BEGIN;
CREATE TRIGGER blah BEFORE INSERT ON test FOR EACH ROW EXECUTE PROCEDURE dummy_tg();
\x
SELECT * FROM pg_locks
WHERE pid = pg_backend_pid()
AND relation = 'test'::regclass;
ROLLBACK;
... which shows that I was wrong about my reading of the sources, because:
locktype | relation
mode | AccessExclusiveLock
it took an AccessExclusiveLock.

Is using the RETURNING clause from an UPDATE as the query clause for an INSERT's query clause possible?

I'm trying to use PostgreSQL's RETURNING clause on an UPDATE within in UPDATE statement, and running into trouble.
Postgres allows a query clause in an INSERT, for example:
INSERT INTO films
SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';
I would like to use the RETURNING clause from an UPDATE as the query clause for an INSERT, for example:
INSERT INTO user_status_history(status)
UPDATE user_status SET status = 'ACTIVE' WHERE status = 'DISABLED' RETURNING status
All of the Postgres references I can find suggest that a RETURNING clause behaved exactly like a SELECT clause,
however when I run something like the above, I get the following:
ERROR: syntax error at or near "UPDATE"
LINE 2: UPDATE user_statuses
Despite being able to execute the UPDATE portion of the above query without error.
Is using the RETURNING clause from an UPDATE as the query clause for an INSERT's query clause possible?
The goal is to update one table and insert into another with a single query, if possible.
With PostgreSQL 9.1 (or higher) you may use the new functionality that allows data-modification commands (INSERT/UPDATE/DELETE) in WITH clauses, such as:
WITH updated_rows AS
(
UPDATE products
SET ...
WHERE ...
RETURNING *
)
INSERT INTO products_log
SELECT * FROM updated_rows;
With PostgreSQL 9.0 (or lower) you may embed the UPDATE command inside one function, and then use that function from another function which performs the INSERT command, such as:
FUNCTION update_rows()
RETURNS TABLE (id integer, descrip varchar)
AS $$
BEGIN
RETURN QUERY
UPDATE products
SET ...
WHERE ...
RETURNING *;
END;
$$ LANGUAGE plpgsql;
FUNCTION insert_rows()
RETURNS void
AS $$
BEGIN
INSERT INTO products_log
SELECT * FROM update_rows() AS x;
END;
$$ LANGUAGE plpgsql;
Right now, no.
There was a feature that almost made it into PostgreSQL 9.0 known as Writeable CTE's that does what you're thinking (although the syntax is different).
Currently, you could either do this via a trigger or as two separate statements.
I think this is not possible the way you are trying to do.
I'd suggest you to write an AFTER UPDATE trigger, which could perform the insert, then.