Attribute notation function call gives error when current schema is different from one of function.
I have created a function
CREATE FU
You found the root of the problem yourself. To be precise: the schema of the function pub
has to be listed anywhere in the current search_path
, does not have to be the "default" or "current" schema (the first one in the list). Related:
So Postgres did not find the function. Postgres 11 isn't different from Postgres 10 in this regard. There are some noteworthy, related developments, though. You mentioned:
Database has been migrated from PostgreSQL 10 with backup/restore.
Consider this subtle change pointed out in the release notes for Postgres 11:
Consider syntactic form when disambiguating function versus column references (Tom Lane)
When
x
is a table name or composite column, PostgreSQL has traditionally considered the syntactic formsf(x)
andx.f
to be equivalent, allowing tricks such as writing a function and then using it as though it were a computed-on-demand column. However, if both interpretations are feasible, the column interpretation was always chosen, leading to surprising results if the user intended the function interpretation. Now, if there is ambiguity, the interpretation that matches the syntactic form is chosen.
So, if there was a column fullname
in table reps
and also the function pub.fullname(pub.reps)
you display, Postgres 10, even with functional notation, would still chose the column:
SELECT fullname(r) FROM reps r; -- resolves to column if it exists, ignoring function
db<>fiddle here for Postgres 10
Postgres 11 (more reasonably) choses the function:
db<>fiddle here for Postgres 11
Postgres 12 (currently beta) eventually implements true generated columns. The release notes:
- Add support for generated columns (Peter Eisentraut)
The content of generated columns are computed from expressions (including references to other columns in the same table) rather than being specified by
INSERT
orUPDATE
commands.
Only STORED
generated columns made it into this release, though. The (more interesting IMO) VIRTUAL variant was postponed for a later release. (Not in Postgres 13, yet.)
Your table could look like this:
CREATE TABLE pub.reps (
reps_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY
, fname text NOT NULL
, lname text NOT NULL
, fullname text GENERATED ALWAYS AS (fname || ' ' || lname) STORED
);
db<>fiddle here
I declared fname
and lname
columns NOT NULL
. Else, your simple concatenation (fname || ' ' || lname
) is a trap. See: