There is a bug connected with invalidation pg catalog cache in trigger functions Another example of this bug I have already reported [1]
The following bug has been logged on the website: Bug reference: 14879 Logged by: Konstantin Evteev Email address: konst583(at)gmail(dot)com PostgreSQL version: 9.4.12 Operating system: Debian GNU/Linux 8 (jessie) Description: -- create database tmp; /* CREATE ROLE test_role LOGIN SUPERUSER INHERIT CREATEDB CREATEROLE REPLICATION; */ -- 1) 1st session psql -U test_role -d tmp tmp=# create table public.test_tbl(test_id int); CREATE TABLE tmp=# DROP SCHEMA if exists _test_schema_1_ cascade; NOTICE: schema "_test_schema_1_" does not exist, skipping DROP SCHEMA tmp=# CREATE SCHEMA _test_schema_1_ AUTHORIZATION postgres; --CREATE SCHEMA tmp=# alter role test_role set search_path = '_test_schema_1_'; --ALTER ROLE CREATE OR REPLACE FUNCTION _test_schema_1_.test_func() RETURNS void AS $BODY$ BEGIN raise notice 'call test func'; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; -- CREATE FUNCTION CREATE OR REPLACE FUNCTION public.trig() returns trigger as $BODY$ BEGIN perform test_func(); return new; END; $BODY$ language plpgsql; --CREATE FUNCTION create trigger t_trig before insert or update on public.test_tbl for each row execute procedure public.trig(); --CREATE TRIGGER 2) 2-nd session psql -U test_role -d tmp insert into public.test_tbl (test_id) values (1); /* NOTICE: call test func INSERT 0 1 */ 3) 1-st session recreate schema 1 DROP SCHEMA if exists _test_schema_1_ cascade; /* NOTICE: drop cascades to function test_func() DROP SCHEMA */ CREATE SCHEMA _test_schema_1_ AUTHORIZATION postgres; -- CREATE SCHEMA CREATE OR REPLACE FUNCTION _test_schema_1_.test_func() RETURNS void AS $BODY$ BEGIN raise notice 'call test func'; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; -- CREATE FUNCTION 4) 2-nd session insert into public.test_tbl (test_id) values (2); /* ERROR: function test_func() does not exist LINE 1: SELECT test_func() ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. QUERY: SELECT test_func() CONTEXT: PL/pgSQL function public.trig() line 3 at PERFORM */ 5) 3-rd session - new session psql -U test_role -d tmp insert into public.test_tbl (test_id) values (3); /* NOTICE: call test func INSERT 0 1 */ 6)Workaround in any session recreate trg function - for example in 3rd session create or replace function public.trig() returns trigger as $BODY$ BEGIN perform test_func(); return new; END; $BODY$ language plpgsql; --CREATE FUNCTION 7) 2nd session insert into public.test_tbl (test_id) values (2); /* NOTICE: call test func INSERT 0 1 */ [1] https://www.postgresql.org/message-id/20171030125345.1448.24...@wrigleys.postgresql.org -- Konstantin Evteev