Нотация атрибута для вызова функции дает ошибку - PullRequest
2 голосов
/ 29 июня 2019

Вызов функции обозначения атрибута выдает ошибку, когда текущая схема отличается от одной из функций.

Я создал функцию

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

Я пытаюсь вызватьфункция с нотацией атрибута, как описано в документы ):

select r.fullname from pub.reps r;

Но выдается сообщение об ошибке:

ERROR:  column "fullname" does not exist

Запрос с функционаломнотация работает отлично:

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

База данных была перенесена из PostgreSQL 10 с резервным копированием / восстановлением.

Select version() дает: PostgreSQL 11.3, compiled by Visual C++ build 1914, 64-bit

UPD .Выяснилось, что если я установлю pub схему по умолчанию, то select r.fullname from pub.reps r будет работать без ошибок.

1 Ответ

2 голосов
/ 30 июня 2019

Вы нашли корень проблемы самостоятельно.Если быть точным: схема функции pub должна быть указана в любом месте в текущей search_path, необязательно должна быть схемой «по умолчанию» или «текущей»(первый в списке).Связанный:

Таким образом, Postgres не нашел функцию.Postgres 11 не отличается от Postgres 10 в этом отношении.Однако есть несколько примечательных связанных событий.Вы упомянули:

База данных была перенесена из PostgreSQL 10 с резервным копированием / восстановлением.

Обратите внимание на это тонкое изменение, указанное в примечаниях к выпуску для Postgres 11 :

  • Учитывать синтаксическую форму при устранении неоднозначности функции по сравнению со ссылками на столбцы (Том Лейн)

    Когда x - это имя таблицы или составной столбец, PostgreSQL традиционно рассматривал синтаксические формы f(x) и x.f длябыть эквивалентным, позволяя использовать такие приемы, как написание функции, а затем использовать ее, как если бы это был столбец с вычислением по требованию.Однако, если обе интерпретации возможны, всегда выбиралась интерпретация столбца, что приводило к неожиданным результатам, если пользователь намеревался интерпретировать функцию.Теперь, если есть неоднозначность, выбирается интерпретация, соответствующая синтаксической форме.

Итак, , если был столбец fullname в таблицеreps , а также отображаемая функция pub.fullname(pub.reps), Postgres 10, даже с функциональной нотацией, все равно выбрал бы столбец :

SELECT fullname(r) FROM reps r;  -- resolves to column if it exists, ignoring function

db <> fiddle здесь для Postgres 10

Postgres 11 (более разумно) выбирает функцию:

db <> fiddle здесь для Postgres 11

Postgres 12 (в настоящее время бета) в конечном итоге реализует истинно сгенерированные столбцы. Примечания к выпуску:

  • Добавить поддержку сгенерированных столбцов (Peter Eisentraut)

Содержимое сгенерированных столбцов вычисляется из выражений (включая ссылки на другие столбцы в той же таблице), вместо того, чтобы быть заданными командами INSERT или UPDATE.

Только STORED сгенерированные столбцы сделали его в этом выпуске, хоть.Вариант (более интересный IMO) VIRTUAL был перенесен на более позднюю версию .Надеясь на Postgres 13.

Ваш стол может выглядеть так:

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 <> скрипка здесь

Я объявил fname и lname столбцы NOT NULL.Иначе, ваша простая конкатенация (fname || ' ' || lname) является ловушкой.См .:

...