10

我需要確定當前爲我的數據庫中的某些物化視圖授予什麼特權。在PostgreSQL中爲物化視圖列出授權和特權

的查詢表或標準視圖做到這一點是相當直截了當:

SELECT grantee, string_agg(privilege_type, ', ') AS privileges 
FROM information_schema.table_privileges 
WHERE table_schema = 'some_schema' AND table_name = 'some_table' 
GROUP by grantee; 

這就是說,似乎沒有成爲物化視圖類似的表。 PostgreSQL在哪裏存儲這些信息?

+0

您的查詢適用於常規視圖,但不適用於物化視圖。 –

回答

4

在Postgres中system catalogs是有關安裝和數據庫的完整信息的基本集合。系統目錄是最可靠的信息來源。 Information schema作爲輔助特性是基於系統目錄,並提供了一種用於與其他RDBMS兼容性:

的信息模式中的SQL標準中定義的,因此可以預期是便攜式的並且保持穩定 - 不像系統目錄,這些目錄是特定於PostgreSQL的,並且是在實現問題之後建模的。但是,信息模式視圖不包含有關PostgreSQL特定功能的信息;查詢需要查詢系統目錄或其他PostgreSQL特定視圖的人員。

物化視圖不是SQL標準對象,因此信息架構不包含有關它們的信息。

系統目錄pg_class包含有關relacl列中特權的所有信息。

如果該列爲null,則擁有者擁有所有權限。

作爲acl中的用戶名的空字符串表示public

create materialized view test_view as select 1; 
grant select on test_view to public; 
grant delete on test_view to a_user; 

select 
    coalesce(nullif(s[1], ''), 'public') as grantee, 
    s[2] as privileges 
from 
    pg_class c 
    join pg_namespace n on n.oid = relnamespace 
    join pg_roles r on r.oid = relowner, 
    unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl, 
    regexp_split_to_array(acl, '=|/') s 
where nspname = 'public' and relname = 'test_view'; 

grantee | privileges 
----------+------------ 
postgres | arwdDxt 
public | r 
a_user | d 
(3 rows) 

您需要一個函數來顯示可讀格式特權:

create or replace function priviliges_from_acl(text) 
returns text language sql as $$ 
    select string_agg(privilege, ', ') 
    from (
     select 
      case ch 
       when 'r' then 'SELECT' 
       when 'w' then 'UPDATE' 
       when 'a' then 'INSERT' 
       when 'd' then 'DELETE' 
       when 'D' then 'TRUNCATE' 
       when 'x' then 'REFERENCES' 
       when 't' then 'TRIGGER' 
      end privilege 
     from 
      regexp_split_to_table($1, '') ch 
    ) s 
$$; 

用途:

select 
    coalesce(nullif(s[1], ''), 'public') as grantee, 
    priviliges_from_acl(s[2]) as privileges 
from 
    pg_class c 
    join pg_namespace n on n.oid = relnamespace 
    join pg_roles r on r.oid = relowner, 
    unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl, 
    regexp_split_to_array(acl, '=|/') s 
where nspname = 'public' and relname = 'test_view'; 

grantee |       privileges       
----------+--------------------------------------------------------------- 
postgres | INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER 
public | SELECT 
a_user | DELETE 
(3 rows) 
+0

非常感謝,這非常有幫助。我發現PostgreSQL允許您在物化視圖上授予諸如UPDATE,INSERT和DELETE之類的權限,這非常有趣。僅僅是因爲他們計劃在未來支持這些行動? –

+1

這是Postgres特權系統的一個特性。通常,即使不適用,也可以授予對象特權。 – klin

+0

*「系統目錄是最可靠的信息來源。」* PostgreSQL的信息模式視圖在哪裏返回不可靠的信息? –

1

繼克林的有用的答案,我想出了一個觀點,即列出pg_class(表,視圖,視圖,索引,序列,外部表,複合類型)中出現的所有關係的所有特權摘要r所有角色:

CREATE VIEW show_privileges AS (
    SELECT 
     grantee, 
     string_agg(relname, ', ' ORDER BY relname) AS rel_names, 
     privileges 
    FROM (
     SELECT 
      relname, 
      coalesce(nullif(s[1], ''), 'public') grantee, 
      (SELECT string_agg(privilege, ', ' ORDER BY privilege ASC) 
       FROM (SELECT 
        CASE ch 
         WHEN 'r' THEN 'SELECT' 
         WHEN 'w' THEN 'UPDATE' 
         WHEN 'a' THEN 'INSERT' 
         WHEN 'd' THEN 'DELETE' 
         WHEN 'D' THEN 'TRUNCATE' 
         WHEN 'x' THEN 'REFERENCES' 
         WHEN 't' THEN 'TRIGGER' 
        END AS privilege 
        FROM regexp_split_to_table(s[2], '') ch 
       ) s 
      ) AS privileges 
     FROM 
      pg_class 
      JOIN pg_namespace ON pg_namespace.oid = relnamespace 
      JOIN pg_roles ON pg_roles.oid = relowner, 
      unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) AS acl, 
      regexp_split_to_array(acl, '=|/') AS s 
     WHERE nspname = 'public' 
    ) AS t 
    GROUP BY grantee, privileges 
    ORDER BY grantee, privileges, rel_names 
);