From 386580b0179cd3f7778f28eea66929571f5e726e Mon Sep 17 00:00:00 2001 From: Laurence Isla Date: Thu, 17 Sep 2026 21:11:34 -0500 Subject: [PATCH] fix: pgrst watch triggers firing up PostgREST notifications unnecessarily - When a trigger is created on a temporary table - When objects are created or dropped inside Supabase schemas: auth, realtime, _realtime, storage --- ...0923021047_update_pgrst_watch_triggers.sql | 63 +++++++++++++++++++ migrations/schema-15.sql | 11 +++- migrations/schema-17.sql | 11 +++- migrations/schema-orioledb-17.sql | 11 +++- 4 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 migrations/db/migrations/20260923021047_update_pgrst_watch_triggers.sql diff --git a/migrations/db/migrations/20260923021047_update_pgrst_watch_triggers.sql b/migrations/db/migrations/20260923021047_update_pgrst_watch_triggers.sql new file mode 100644 index 0000000000..500fbdc3a1 --- /dev/null +++ b/migrations/db/migrations/20260923021047_update_pgrst_watch_triggers.sql @@ -0,0 +1,63 @@ +-- migrate:up + +CREATE OR REPLACE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger + LANGUAGE plpgsql + AS $$ +DECLARE + cmd record; +BEGIN + FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands() + LOOP + IF cmd.command_tag IN ( + 'CREATE SCHEMA', 'ALTER SCHEMA' + , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE' + , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE' + , 'CREATE VIEW', 'ALTER VIEW' + , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' + , 'CREATE FUNCTION', 'ALTER FUNCTION' + , 'CREATE TYPE', 'ALTER TYPE' + , 'CREATE RULE' + , 'COMMENT' + ) + -- don't notify in case of CREATE TEMP table or other objects created on pg_temp + -- also exclude any objects inside Supabase schemas + AND COALESCE(cmd.schema_name, '') NOT IN ('pg_temp', 'auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR (cmd.command_tag = 'CREATE TRIGGER' AND cmd.object_identity NOT LIKE '% pg\_temp.%') + THEN + NOTIFY pgrst, 'reload schema'; + END IF; + END LOOP; +END; $$; + + +CREATE OR REPLACE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger + LANGUAGE plpgsql + AS $$ +DECLARE + obj record; +BEGIN + FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() + LOOP + IF obj.object_type IN ( + 'schema' + , 'table' + , 'foreign table' + , 'view' + , 'materialized view' + , 'function' + , 'type' + , 'rule' + ) + AND obj.is_temporary IS false -- no pg_temp objects + -- also exclude any objects inside Supabase schemas + AND COALESCE(obj.schema_name, '') NOT IN ('auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR ( obj.object_type = 'trigger' AND obj.object_identity NOT LIKE '% pg\_temp.%') + THEN + NOTIFY pgrst, 'reload schema'; + END IF; + END LOOP; +END; $$; + +-- migrate:down diff --git a/migrations/schema-15.sql b/migrations/schema-15.sql index 322f47404c..5a57162693 100644 --- a/migrations/schema-15.sql +++ b/migrations/schema-15.sql @@ -339,13 +339,15 @@ BEGIN , 'CREATE VIEW', 'ALTER VIEW' , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' , 'CREATE FUNCTION', 'ALTER FUNCTION' - , 'CREATE TRIGGER' , 'CREATE TYPE', 'ALTER TYPE' , 'CREATE RULE' , 'COMMENT' ) -- don't notify in case of CREATE TEMP table or other objects created on pg_temp - AND cmd.schema_name is distinct from 'pg_temp' + -- also exclude any objects inside Supabase schemas + AND COALESCE(cmd.schema_name, '') NOT IN ('pg_temp', 'auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR (cmd.command_tag = 'CREATE TRIGGER' AND cmd.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF; @@ -372,11 +374,14 @@ BEGIN , 'view' , 'materialized view' , 'function' - , 'trigger' , 'type' , 'rule' ) AND obj.is_temporary IS false -- no pg_temp objects + -- also exclude any objects inside Supabase schemas + AND COALESCE(obj.schema_name, '') NOT IN ('auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR ( obj.object_type = 'trigger' AND obj.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF; diff --git a/migrations/schema-17.sql b/migrations/schema-17.sql index 2cbfa1b146..742901630f 100644 --- a/migrations/schema-17.sql +++ b/migrations/schema-17.sql @@ -340,13 +340,15 @@ BEGIN , 'CREATE VIEW', 'ALTER VIEW' , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' , 'CREATE FUNCTION', 'ALTER FUNCTION' - , 'CREATE TRIGGER' , 'CREATE TYPE', 'ALTER TYPE' , 'CREATE RULE' , 'COMMENT' ) -- don't notify in case of CREATE TEMP table or other objects created on pg_temp - AND cmd.schema_name is distinct from 'pg_temp' + -- also exclude any objects inside Supabase schemas + AND COALESCE(cmd.schema_name, '') NOT IN ('pg_temp', 'auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR (cmd.command_tag = 'CREATE TRIGGER' AND cmd.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF; @@ -373,11 +375,14 @@ BEGIN , 'view' , 'materialized view' , 'function' - , 'trigger' , 'type' , 'rule' ) AND obj.is_temporary IS false -- no pg_temp objects + -- also exclude any objects inside Supabase schemas + AND COALESCE(obj.schema_name, '') NOT IN ('auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR ( obj.object_type = 'trigger' AND obj.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF; diff --git a/migrations/schema-orioledb-17.sql b/migrations/schema-orioledb-17.sql index d4fb8c6198..a592bb8105 100644 --- a/migrations/schema-orioledb-17.sql +++ b/migrations/schema-orioledb-17.sql @@ -354,13 +354,15 @@ BEGIN , 'CREATE VIEW', 'ALTER VIEW' , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' , 'CREATE FUNCTION', 'ALTER FUNCTION' - , 'CREATE TRIGGER' , 'CREATE TYPE', 'ALTER TYPE' , 'CREATE RULE' , 'COMMENT' ) -- don't notify in case of CREATE TEMP table or other objects created on pg_temp - AND cmd.schema_name is distinct from 'pg_temp' + -- also exclude any objects inside Supabase schemas + AND COALESCE(cmd.schema_name, '') NOT IN ('pg_temp', 'auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR (cmd.command_tag = 'CREATE TRIGGER' AND cmd.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF; @@ -387,11 +389,14 @@ BEGIN , 'view' , 'materialized view' , 'function' - , 'trigger' , 'type' , 'rule' ) AND obj.is_temporary IS false -- no pg_temp objects + -- also exclude any objects inside Supabase schemas + AND COALESCE(obj.schema_name, '') NOT IN ('auth', 'realtime', '_realtime', 'storage') + -- Exclude any trigger created on temp tables (object_identity = 'trigger on pg_temp.table') + OR ( obj.object_type = 'trigger' AND obj.object_identity NOT LIKE '% pg\_temp.%') THEN NOTIFY pgrst, 'reload schema'; END IF;