Attribute notation for function call gives error

蹲街弑〆低调 提交于 2019-12-01 23:04:07

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 forms f(x) and x.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 or UPDATE commands.

Only STORED generated columns made it into this release, though. The (more interesting IMO) VIRTUAL variant was postponed for a later release. Hoping for Postgres 13.

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:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!