У меня есть следующая функция, которую я хотел бы использовать в sql-запросе (Postgres 9.3):
SELECT * FROM test_table tt WHERE has_access(tt.id, tt.login)
CREATE OR REPLACE FUNCTION has_access(integer, integer)
RETURNS boolean AS
$BODY$
SELECT
EXISTS (SELECT true
FROM test_read_access
WHERE id = $1 and login = $2
)
AND
NOT EXISTS (SELECT true
FROM test_no_read_access
WHERE id = $1 and login = $2
)
$BODY$
Это прекрасно работает, пока мне приходится заботиться только о функциональной корректности. Поскольку анализатор запросов говорит мне, что функция должна оцениваться для каждой строки, и поэтому предложения EXISTS не могут быть оптимизированы должным образом. Действительно, запрос очень медленный по сравнению со следующим запросом (встраивание предложений EXISTS без предложения SELECT):
SELECT * FROM test_table tt WHERE
EXISTS (SELECT true
FROM test_read_access
WHERE id = tt.id and login = tt.login
)
AND
NOT EXISTS (SELECT true
FROM test_no_read_access
WHERE id = tt.id and login = tt.login
)
Назначение функции has_access(id, login) состоит в том, чтобы сгруппировать некоторое правило доступа в функции и затем использовать его в разных запросах. Я имею в виду, что можно сделать что-то подобное, чтобы получить хорошую производительность:
SELECT * FROM test_table tt WHERE EXISTS (select has_access(tt.id, tt.login))
CREATE OR REPLACE FUNCTION has_access(integer, integer)
RETURNS SETOF boolean AS
$BODY$
SELECT true
FROM test_read_access
WHERE id = $1 and login = $2
$BODY$
Но теперь у меня есть только один подзапрос к одной таблице в функции, и в моем случае это бесполезно. Любое предложение о том, как сделать это правильно, чтобы не столкнуться с проблемами производительности?
Спасибо!