Возврат логического значения из функции SQL

Я пытаюсь написать функцию PL/pgSQL в postgres, которая возвращает логическое выражение. В настоящее время код выглядит так:

CREATE OR REPLACE FUNCTION is_visible_to(role integer, from_role integer)
  RETURNS boolean
  LANGUAGE SQL STABLE STRICT AS $$
    RETURN $1 = $2 OR first_predicate($1, $2) OR second_predicate($2, $1);
 $$;

Функции first_predicate и second_predicate существуют и возвращают логические значения, но я не получаю особой помощи, глядя на них, потому что они определены чем-то вроде

SELECT COUNT(*) > 0 FROM ... WHERE ...

Я получаю следующую синтаксическую ошибку:

ERROR:  syntax error at or near "RETURN"
LINE 4:     RETURN $1 = $2 first_predicate($1, $2) OR second_predicate(...
            ^

Так что, очевидно, я неправильно понимаю что-то довольно фундаментальное здесь. Я новичок во всем, что связано с PL/pgSQL, поэтому ссылки на хороший учебник или два также будут оценены.

Проект, над которым я работаю, использует исключительно postgres и уже содержит много кода, специфичного для postgres, поэтому решения не должны переноситься на другие базы данных.

Редактировать: Исправил сам с помощью

CREATE FUNCTION is_visible_to (role integer, from_role integer)
  RETURNS BOOLEAN AS '
    DECLARE
        role ALIAS FOR $1;
        from_role ALIAS FOR $2;
    BEGIN
      RETURN (role = from_role) OR
             first_predicate(from_role, role) OR
             second_predicate(from_role, role)
    END;
' LANGUAGE 'plpgsql';

Все равно был бы признателен за ответ, объясняющий, почему более поздние версии работают, а первые (даже с измененным на plpgsql языком, как это было предложено @a_horse_with_no_name) не работают, или предоставляет некоторые полезные учебные пособия.


person jjm    schedule 02.12.2014    source источник
comment
Ваша функция определена как language sql. В sql нет оператора return, только в PL/pgSQL   -  person a_horse_with_no_name    schedule 03.12.2014
comment
@a_horse_with_no_name Я изменил language sql на langauge plpgsql, та же ошибка.   -  person jjm    schedule 03.12.2014
comment
Работает с language sql: sqlfiddle.com/#!15/7cf4a/1 и plpgsql: sqlfiddle.com/#!15/90f62/1 Кстати: название языка идентификатор, поэтому без одинарных кавычек, пожалуйста, plpgsql или sql, но не 'plpgsql'   -  person a_horse_with_no_name    schedule 03.12.2014
comment
@a_horse_with_no_name извините, я сделал еще одну глупость. Спасибо.   -  person jjm    schedule 03.12.2014


Ответы (1)


SQL

CREATE OR REPLACE FUNCTION is_visible_to(role integer, from_role integer)
  RETURNS boolean AS
$func$
   SELECT $1 = $2 OR first_predicate($1, $2) OR second_predicate($2, $1);
$func$ LANGUAGE sql STABLE STRICT;

С SELECT. В простом SQL нет RETURN. Подробности в руководстве здесь.

PL/pgSQL

CREATE OR REPLACE FUNCTION is_visible_to(role integer, from_role integer)
  RETURNS boolean AS
$func$
BEGIN
   RETURN $1 = $2 OR first_predicate($1, $2) OR second_predicate($2, $1);
END
$func$ LANGUAGE plpgsql STABLE STRICT;

BEGIN и END необходимы для PL/pgSQL. Подробности в руководстве здесь.

Не используйте устаревший (и избыточный здесь) синтаксис ALIAS FOR. В руководстве это не рекомендуется. Вы может напрямую ссылаться на имена параметров (также и в функциях SQL, начиная с стр. 9.2).

person Erwin Brandstetter    schedule 03.12.2014
comment
Есть ли причина, по которой вы называете аргументы $1 и $2 вместо role и from_role в теле функции? - person Jay; 05.04.2016
comment
@Jay: Любой из них действителен в функциях Postgres 9.2+. ОП не раскрыл свою версию, поэтому позиционные ссылки были беспроигрышной ставкой. В конце моего ответа есть подсказка. Подробнее: stackoverflow.com/a/27116711/939860 - person Erwin Brandstetter; 05.04.2016