Thread: [BUGS] BUG #14649: Function Namespace Resolution Bug

[BUGS] BUG #14649: Function Namespace Resolution Bug

From
jeremy@cowgar.com
Date:
The following bug has been logged on the website:

Bug reference:      14649
Logged by:          Jeremy Cowgar
Email address:      jeremy@cowgar.com
PostgreSQL version: 9.6.1
Operating system:   Debian
Description:

We ran across an issue restoring our database recently and have tracked it
down. The following SQL exposes the bug. It appears to deal with a confusion
of schema namespaces, thus the "create schema g” line is vital to expose
this problem.

In short, when a CHECK on a column in a different schema references a
function in public that references another function in public implicitly,
there is confusion. The workaround is to prefix the function calls with the
schema.

Here is the SQL to expose the problem. Below I have included the commands
necessary to create the database, import the data, then dump and restore.
The restore is where we are seeing the bug.


—— SQL ——

create or replace function is_blank(data text) returns boolean language plpgsql as $$
begin return false;
end $$;

create or replace function has_content(data text) returns boolean language plpgsql as $$
begin return not is_blank(data);
end $$;

create schema g;

create table g.people ( id serial, name varchar(50) not null, check (has_content(name))
);

insert into g.people (name) values ('John’);

—— END SQL ——


—— TERMINAL OUTPUT ——

$ createdb -O postgres -U postgres dummy && psql -U postgres dummy <
dummy.sql
CREATE FUNCTION
CREATE FUNCTION
CREATE SCHEMA
CREATE TABLE
INSERT 0 1

$ createdb -U postgres dummy_restore && pg_dump -U postgres -Fc -Z9 dummy |
pg_restore -U postgres -d dummy_restore
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 2367; 0 1055467702 TABLE
DATA people postgres
pg_restore: [archiver (db)] COPY failed for table "people": ERROR: function
is_blank(text) does not exist
LINE 1: SELECT not is_blank(data)
^
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
QUERY: SELECT not is_blank(data)
CONTEXT: PL/pgSQL function public.has_content(text) line 3 at RETURN
COPY people, line 1: "1 John"
WARNING: errors ignored on restore: 1

—— END TERMINAL OUTPUT ——


Thank you,

Jeremy Cowgar


--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14649: Function Namespace Resolution Bug

From
Tom Lane
Date:
jeremy@cowgar.com writes:
> In short, when a CHECK on a column in a different schema references a
> function in public that references another function in public implicitly,
> there is confusion. The workaround is to prefix the function calls with the
> schema.

I don't see any PG bug here.  If you don't schema-qualify the function
reference, then it is dependent on the current search_path, and pg_dump/
pg_restore have their own ideas about how to set search_path.  Even if
those two somehow magically intuited what search_path you're expecting,
this coding would still be fragile since some other user might use a
different search_path than you while accessing the table.  The schema
qualification isn't a "workaround", it's just good coding practice.
        regards, tom lane


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14649: Function Namespace Resolution Bug

From
Jeremy Cowgar
Date:
Why does it find the initial function just fine in the public namespace, but the method it calls it can not find, which
isin the same namespace as the calling function? 

Jeremy Cowgar

> On May 12, 2017, at 2:13 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> jeremy@cowgar.com writes:
>> In short, when a CHECK on a column in a different schema references a
>> function in public that references another function in public implicitly,
>> there is confusion. The workaround is to prefix the function calls with the
>> schema.
>
> I don't see any PG bug here.  If you don't schema-qualify the function
> reference, then it is dependent on the current search_path, and pg_dump/
> pg_restore have their own ideas about how to set search_path.  Even if
> those two somehow magically intuited what search_path you're expecting,
> this coding would still be fragile since some other user might use a
> different search_path than you while accessing the table.  The schema
> qualification isn't a "workaround", it's just good coding practice.
>
>             regards, tom lane



--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14649: Function Namespace Resolution Bug

From
Tom Lane
Date:
Jeremy Cowgar <jeremy@cowgar.com> writes:
> Why does it find the initial function just fine in the public namespace, but the method it calls it can not find,
whichis in the same namespace as the calling function? 

pg_dump is smart enough to schema-qualify that one.  If you look at
the actual dump output for the table, it looks like

SET search_path = g, pg_catalog;
...
CREATE TABLE people (   id integer NOT NULL,   name character varying(50) NOT NULL,   CONSTRAINT people_name_check
CHECK(public.has_content((name)::text)) 
);

However, editing the body text of your function is beyond pg_dump's
competence.
        regards, tom lane


--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14649: Function Namespace Resolution Bug

From
Jeremy Cowgar
Date:
I didn’t realize that pg_dump alters the search path. Couldn’t pg_dump simply append the default search path to the end
ofit’s custom setting? That should solve the problem as well? We have not changed our search path and it seems the
defaultis “$user”, public. 

Jeremy Cowgar

> On May 12, 2017, at 2:50 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Jeremy Cowgar <jeremy@cowgar.com> writes:
>> Why does it find the initial function just fine in the public namespace, but the method it calls it can not find,
whichis in the same namespace as the calling function? 
>
> pg_dump is smart enough to schema-qualify that one.  If you look at
> the actual dump output for the table, it looks like
>
> SET search_path = g, pg_catalog;
> ...
> CREATE TABLE people (
>    id integer NOT NULL,
>    name character varying(50) NOT NULL,
>    CONSTRAINT people_name_check CHECK (public.has_content((name)::text))
> );
>
> However, editing the body text of your function is beyond pg_dump's
> competence.
>
>             regards, tom lane



--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14649: Function Namespace Resolution Bug

From
Tom Lane
Date:
Jeremy Cowgar <jeremy@cowgar.com> writes:
> I didn’t realize that pg_dump alters the search path. Couldn’t pg_dump
> simply append the default search path to the end of it’s custom setting?

There's no particularly good reason to believe that there's a single
"default" search_path that would apply to all usages in a given database.
Even if there were, sticking another schema in front of it wouldn't
produce the same results, ie if you have code that fails when the
search_path isn't "f, g, h", it may well fail when the search_path is
"g, f, g, h", because schema g would win ambiguous references over
schema f.

We could maybe make this work if pg_dump never touched the search_path
at all, but that would be a quite subtle change creating its own set of
hazards.

The long and the short of it is that code in CHECK constraints (or
triggers) is well advised not to depend on any particular search_path;
blaming pg_dump for exposing that is just shooting the messenger.
        regards, tom lane


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs