web-dev-qa-db-ja.com

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はこの情報をどこに保存しますか?

12
Luke Sapan

Postgresでは システムカタログ はインストールとデータベースに関する完全な情報の基本セットです。システムカタログは、最も信頼できる情報源です。 情報スキーマ 補助機能はシステムカタログに基づいており、他のRDBMとの互換性のために提供されています。

情報スキーマは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)
5
klin

Klinの有益な回答に続いて、pg_class(テーブル、ビュー、m。ビュー、インデックス、シーケンス、外部テーブル、複合型)に表示されるすべてのリレーションのすべての特権の概要を一覧表示するビューを思いつきました。すべての役割の場合:

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
);
1
gilad mayani