Attribute notation for function call gives error

与世无争的帅哥 提交于 2019-12-02 03:06:44

问题


Attribute notation function call gives error when current schema is different from one of function.

I have created a function

CREATE FUNCTION pub.FullName(pub.reps)
  RETURNS text AS
$func$
       select ($1.fname || ' ' || $1.lname)
$func$ LANGUAGE SQL;

I am trying to call the function with attribute notation as described in docs):

select r.fullname from pub.reps r;

But get an error message:

ERROR:  column "fullname" does not exist

Query with functional notation works fine:

select pub.fullname(r.*) from pub.reps r;

Database has been migrated from PostgreSQL 10 with backup/restore.

Select version() gives: PostgreSQL 11.3, compiled by Visual C++ build 1914, 64-bit

UPD. Found out that if I set pub schema as default, then select r.fullname from pub.reps r works with no error.


回答1:


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:

  • How does the search_path influence identifier resolution and the "current schema"

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:

  • How to concatenate columns in a Postgres SELECT?
  • Combine two columns and add into one new column


来源:https://stackoverflow.com/questions/56816432/attribute-notation-for-function-call-gives-error

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