I derive from your previous question that you are using PostgreSQL 8.4, which is pretty outdated by now.
You need to provide this information with every question!
In your function header you declare
RETURNS TABLE(user_id INT4, permission_id INT4)
The OUT
parameters user_id
and permission_id
are visible everywhere in the function body in PL/pgSQL. To avoid naming conflicts you need to table-qualify columns of the same name. Your function would not work properly with modern Postgres either, since the reference in your final SELECT
would return NULL
values:
SELECT user_id, permission_id
Postgres 8.4 had more problems with that and errors out at
SELECT unnest(affected_user_list) AS user_id
The naming conflict is unacceptable to the old version. Newer versions have resolved this.
sql function
You can use this SQL function with a largely simplified query instead:
CREATE FUNCTION permission_cache_update(affected_user_list int[])
RETURNS TABLE(user_id int, permission_id int) AS
$func$
WITH affected_user AS (SELECT unnest($1) AS user_id)
SELECT a.user_id, r.permission_id
FROM user_role u
JOIN role_permission r USING (role_id)
JOIN affected_user a USING (user_id)
UNION
SELECT a.user_id, p.permission_id
FROM user_permission p
JOIN affected_user a USING (user_id)
$func$ LANGUAGE sql;
Use proper join syntax. Much easier to read and maintain.
I also simplified with USING
, which is a matter of taste and style. It's simpler and shorter, but requires unambiguous column names. So that would not work in a plpgsql version for Postgres 8.4 either, but works in modern versions.
The final SELECT
with the GROUP BY
in your original query is just noise.
UNION
(as opposed to UNION ALL
) already implicitly removes duplicates.
plpgsql function
If you avoid the naming conflicts, the plpgsql version should also work:
CREATE FUNCTION permission_cache_update(affected_user_list int[])
RETURNS TABLE(user_id int, permission_id int) AS
$func$
BEGIN
RETURN QUERY
WITH affected_user AS (
SELECT unnest(affected_user_list) AS u_id
)
SELECT a.user_id, r.permission_id
FROM user_role u
JOIN role_permission r USING (role_id)
JOIN affected_user a ON a.u_id = u.user_id
UNION
SELECT a.user_id, p.permission_id
FROM user_permission p
JOIN affected_user a ON a.u_id = p.user_id;
END
$func$ LANGUAGE plpgsql;