The following query stopped working when upgrading from PostgreSQL 9.6 to 11:
with doc as (select * from documents where name = doc_id)
select jsonb_array_elements_text(permissions)
from users
where users.name = user_name
union
select
case
when doc.reader = user_name then 'read'
when doc.owner = user_name then unnest(array['read','write'])
else unnest(array[]::text[])
end
from doc;
The union
as usual puts together two lists of values, both lists can have zero, one or more elements.
The first select
can return zero, one or more just because that's what's in the users
table.
The second select
always scans one row from the documents
table, but returns zero, one or more rows depending on what the case
decides.
PostgreSQL 9.6 was working as expected, PostgreSQL 11 says:
ERROR: set-returning functions are not allowed in CASE
LINE 56: else unnest(array[]::text[])
^
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
I appreciate the advice, but I can't figure out how to use a LATERAL FROM
here.
The hint is a bit misleading here. As it says, adding lateral joins to your set-returning functions might help (in general), but I don't think it makes much sense in your case.
You can easily work around this by changing the CASE
expression to return an array, and then unnesting the result:
...
select
unnest(
case
when doc.reader = user_name then array['read']
when doc.owner = user_name then array['read','write']
else array[]::text[]
end
)
from doc;