I have the following function which I'd like to use in a sql query (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$
This works fine as long as I have to concern only about functional correctness. Because the query analyzer tells me, that the function has to be evaluated for every row and therefore the EXISTS-clauses cannot be optimized as expected. Indeed the query is very slow compared to the following query (inlining the EXISTS-clauses without the SELECT-clause):
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
)
The intention of the function has_access(id, login) is to group some access rule in a function and to use it then in different queries. I mean, it is possible to do something like this to get a good performance:
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$
But now I only have one sub query on one table in the function and this is not useful in my case. Any suggestion on how to do this properly in order to not run into performance issues?
Thanks!