BUG #15534: Operators from public schema in trigger WHEN-clauses aresilently allowed despite breaking restores
От | PG Bug reporting form |
---|---|
Тема | BUG #15534: Operators from public schema in trigger WHEN-clauses aresilently allowed despite breaking restores |
Дата | |
Msg-id | 15534-b06638e5850f55b7@postgresql.org обсуждение исходный текст |
Ответы |
Re: BUG #15534: Operators from public schema in trigger WHEN-clauses are silently allowed despite breaking restores
|
Список | pgsql-bugs |
The following bug has been logged on the website: Bug reference: 15534 Logged by: Patrick O'Toole Email address: p.otoole@uwyo.edu PostgreSQL version: 9.6.11 Operating system: Amazon Linux Description: Apologies in advance if this has been raised already. I encountered a problem while trying to copy a few structures to a separate database for testing via pg_dump and pg_restore.The issue seems to be that operators found in the public schema (which may be put there by extensions) are made unavailable during restore to prevent ambiguity across different namespaces. In my case, this was a PostGIS operator, but using `\do` from psql after altering the 'search_path' setting shows this might be a pitfall that is generally possible against various extensions' custom operators (e.g. hstore). As such, I'm reporting the problem here first. Since a typical user may not always be aware of which operators are are built-ins from pg_catalog and which are made available in schema "public" via extensions, it might be good to prevent use of unsafe operators or at least issue a warning on parsing WHEN expressions during trigger-creation. Otherwise, I might expect Postgres to encode these operators so they can be restored without issue; the current behavior silently creates surprises which can halt database-restores attempted later on. The reproduction-steps I give below use pg_dump and psql started from within a command-shell. -- from psql: DROP DATABASE IF EXISTS temp; CREATE DATABASE temp; \c temp CREATE EXTENSION IF NOT EXISTS postgis; CREATE TABLE t( id SERIAL PRIMARY KEY, geom GEOMETRY ); CREATE OR REPLACE FUNCTION f() RETURNS trigger AS $$ BEGIN RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER tr BEFORE UPDATE ON t FOR EACH ROW WHEN ( NEW.geom IS DISTINCT FROM OLD.geom ) EXECUTE PROCEDURE f(); DROP DATABASE IF EXISTS restore_test; CREATE DATABASE restore_test; -- [now exit psql] \q # Now from the shell: # dump schema to file: pg_dump temp -s -f temp.sql # restore to empty database: psql restore_test -f temp.sql # Receive error: # CREATE TRIGGER tr BEFORE UPDATE ON public.t FOR EACH ROW WHEN ((new.geom IS DISTINCT FROM old.geom)) EXECUTE PROCEDURE public.f(); # psql:temp:159: ERROR: operator is not unique: public.geometry = public.geometry # LINE 1: ...E UPDATE ON public.t FOR EACH ROW WHEN ((new.geom IS DISTINC... # ^ # HINT: Could not choose a best candidate operator. You might need to add explicit type casts. The same error will occur if using `pg_dump -F d` and `pg_restore` instead of psql and the default plain dump. Adding type-casts of ::public.GEOMETRY has no effect, and the reconstructed node-tree in the WHEN-expression does not appear different per the restore-script. This gotcha can explained by performing `\do =` from within psql with 'search_path' as the default "$user",public versus the environment during restores obtained by doing set_config('search_path','',false). As an aside, a workaround for the issue is to create a wrapper-function for the comparison instead of placing it directly in the WHEN clause. Having tracked my problem down, the answer of "just don't use problem-operators directly that way" seems obvious, but it might not be for all users, which is why I'm writing. Thanks to all, - Patrick O'Toole Full OS (uname -a): Linux 4.14.77-69.57.amzn1.x86_64 #1 SMP Tue Nov 6 21:32:55 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux Full Postgres version: PostgreSQL 9.6.11 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit
В списке pgsql-bugs по дате отправления: