You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redshift中information_schema.table_privileges不支持TRUNCATE权限的原因及替代方案

问题

需要查询用户对表拥有的SELECT、INSERT、UPDATE、DELETE及TRUNCATE权限,但information_schema.table_privileges视图无法显示TRUNCATE权限。尝试在makeaclitem()函数中加入TRUNCATE类型时出现错误,求替代方法。

原查询代码:

SELECT u_grantor.usename::information_schema.sql_identifier AS grantor, 
        grantee.name::information_schema.sql_identifier AS grantee, 
        current_database()::information_schema.sql_identifier AS table_catalog, 
        nc.nspname::information_schema.sql_identifier AS table_schema, 
        c.relname::information_schema.sql_identifier AS table_name, 
        pr."type"::information_schema.character_data AS privilege_type 
FROM pg_class c, pg_namespace nc, pg_user u_grantor,
(SELECT pg_user.usesysid, 0, pg_user.usename FROM pg_user ) grantee(usesysid, grosysid, name), 
(((((( SELECT 'SELECT'::character varying
        UNION ALL 
        SELECT 'DELETE'::character varying)
        UNION ALL 
        SELECT 'INSERT'::character varying)
        UNION ALL 
        SELECT 'UPDATE'::character varying)
        UNION ALL 
        SELECT 'REFERENCES'::character varying)
        UNION ALL 
        SELECT 'TRUNCATE'::character varying)
        UNION ALL 
        SELECT 'TRIGGER'::character varying) pr("type")
        WHERE c.relnamespace = nc.oid 
AND c.relkind = 'r'::"char"
AND aclcontains(c.relacl, makeaclitem(grantee.usesysid, grantee.grosysid, u_grantor.usesysid, pr."type"::text, false))

错误信息:

SQL Error [22023]: ERROR: unrecognized privilege type: "TRUNCATE"
解决方案

PostgreSQL中makeaclitem()函数不接受'TRUNCATE'作为权限类型参数,因为TRUNCATE权限的内部标识是缩写代码而非完整字符串。以下是两种可行的解决方法:

方法1:拆分查询,用权限缩写单独处理TRUNCATE

将原查询拆分为常规权限查询和TRUNCATE权限查询两部分,用UNION ALL合并结果。TRUNCATE权限对应的内部缩写是'T',可以直接传入makeaclitem函数:

-- 查询常规表权限(SELECT/INSERT/UPDATE/DELETE等)
SELECT u_grantor.usename::information_schema.sql_identifier AS grantor, 
        grantee.name::information_schema.sql_identifier AS grantee, 
        current_database()::information_schema.sql_identifier AS table_catalog, 
        nc.nspname::information_schema.sql_identifier AS table_schema, 
        c.relname::information_schema.sql_identifier AS table_name, 
        pr."type"::information_schema.character_data AS privilege_type 
FROM pg_class c, pg_namespace nc, pg_user u_grantor,
(SELECT pg_user.usesysid, 0, pg_user.usename FROM pg_user ) grantee(usesysid, grosysid, name), 
((((( SELECT 'SELECT'::character varying
        UNION ALL 
        SELECT 'DELETE'::character varying)
        UNION ALL 
        SELECT 'INSERT'::character varying)
        UNION ALL 
        SELECT 'UPDATE'::character varying)
        UNION ALL 
        SELECT 'REFERENCES'::character varying)
        UNION ALL 
        SELECT 'TRIGGER'::character varying) pr("type")
WHERE c.relnamespace = nc.oid 
AND c.relkind = 'r'::"char"
AND aclcontains(c.relacl, makeaclitem(grantee.usesysid, grantee.grosysid, u_grantor.usesysid, pr."type"::text, false))

UNION ALL

-- 单独查询TRUNCATE权限
SELECT 
    u_grantor.usename::information_schema.sql_identifier AS grantor,
    grantee.name::information_schema.sql_identifier AS grantee,
    current_database()::information_schema.sql_identifier AS table_catalog,
    nc.nspname::information_schema.sql_identifier AS table_schema,
    c.relname::information_schema.sql_identifier AS table_name,
    'TRUNCATE'::information_schema.character_data AS privilege_type
FROM pg_class c
JOIN pg_namespace nc ON c.relnamespace = nc.oid
JOIN pg_user grantee ON TRUE
JOIN pg_user u_grantor ON TRUE
WHERE c.relkind = 'r'::"char"
AND aclcontains(c.relacl, makeaclitem(grantee.usesysid, 0, u_grantor.usesysid, 'T', false));

方法2:直接解析relacl字段提取权限

pg_class.relacl字段存储了表的所有权限项,每个项是aclitem类型,可以通过拆解其文本格式来提取TRUNCATE及其他权限:

SELECT
    (split_part(aclitem::text, '=', 1))::information_schema.sql_identifier AS grantee,
    (split_part(aclitem::text, '=', 2))::information_schema.sql_identifier AS grantor,
    current_database()::information_schema.sql_identifier AS table_catalog,
    nc.nspname::information_schema.sql_identifier AS table_schema,
    c.relname::information_schema.sql_identifier AS table_name,
    CASE
        WHEN position('r' in split_part(aclitem::text, '/', 1)) > 0 THEN 'SELECT'
        WHEN position('w' in split_part(aclitem::text, '/', 1)) > 0 THEN 'UPDATE'
        WHEN position('a' in split_part(aclitem::text, '/', 1)) > 0 THEN 'INSERT'
        WHEN position('d' in split_part(aclitem::text, '/', 1)) > 0 THEN 'DELETE'
        WHEN position('T' in split_part(aclitem::text, '/', 1)) > 0 THEN 'TRUNCATE'
        WHEN position('x' in split_part(aclitem::text, '/', 1)) > 0 THEN 'REFERENCES'
        WHEN position('t' in split_part(aclitem::text, '/', 1)) > 0 THEN 'TRIGGER'
    END::information_schema.character_data AS privilege_type
FROM pg_class c
JOIN pg_namespace nc ON c.relnamespace = nc.oid
LEFT JOIN unnest(c.relacl) AS aclitem ON TRUE
WHERE c.relkind = 'r'::"char"
AND aclitem IS NOT NULL;

这种方法无需依赖makeaclitem函数,直接解析原始权限数据,兼容性更强。

内容的提问来源于stack exchange,提问作者eeeeeeeeeee21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 19:54:50