升级到PostgreSQL 11:在CASE中不允许使用返回值的函数

时间:2019-06-12 22:07:28

标签: sql postgresql lateral

从PostgreSQL 9.6升级到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;

union和往常一样将两个值列表放在一起,两个列表都可以包含零个,一个或多个元素。

第一个select可以返回零,一个或多个可以仅仅是因为users表中的内容。

第二个select总是扫描documents表中的一行,但返回零,取决于case的决定是一行还是多行。

PostgreSQL 9.6可以按预期工作,PostgreSQL 11说:

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.

我很感谢您的建议,但是在这里我不知道如何使用LATERAL FROM

1 个答案:

答案 0 :(得分:2)

这里的提示有点误导。就像说的那样,向您的集合返回函数中添加横向联接可能帮助(通常),但我认为这对您来说没有太大意义。

您可以通过更改CASE表达式以返回数组,然后取消嵌套结果来轻松解决此问题:

...
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;