我有一个数组,列值为
{james = UC / james,adam = C / james,chris = U C / james,john = U / james}
以上列的值不是json。它们是以下形式的字符串:
{ username=privilegestring/grantor }
如何将上面的列转换为多行
答案 0 :(得分:0)
编辑#3:
通过CTE pg_catalog 将查询更新为专门针对pg_catalog.pg_namespace的ACL权限授予。当前,此CTE已在where子句中进行过滤以选择单个名称空间名称('avengers'
);如果要从多个名称空间名称中进行选择,则应该可以将它们直接添加到此CTE的WHERE
子句中,或者在需要所有名称空间名称的情况下,请完全删除该子句。 < / p>
同样值得注意的是,您将需要扩展access_privilege_types
中的case语句来处理所有权限情况:“ r”,“ w”,“ a”,“ d”和'x',分别用于SELECT
,UPDATE
,INSERT
,DELETE
,REFERENCE
。
编辑#2:
下面的查询的最终发布版本将以所需的格式为您提供所需的数据。如果当前所指定的两个以上,则需要在CTE * access_privilege_types
*中扩展case语句。显然,您还需要在查询中替换表名,等等。如果您遇到任何麻烦,请告诉我,我们将在必要时为您提供帮助。
编辑#1:
能够验证此查询在Redshift中是否有效。更新了查询,以按授权人和所有者分开单独的行。当前版本尚未按行细分个人权限-今晚晚些时候看一下我是否也能正常工作。
原始:
目前,我无法访问Redshift集群进行测试,但是到家后就可以进行测试。以下方法的总体思路是,创建一个编号索引表进行交叉连接,以将权限字段中的数据扩展为基于行的表示形式。
我曾经询问过大小限制,因为当前只能处理10,000个可能的定界值,但是如果您的特定应用需要,您可以调整CTE以扩大到更大的数量:
修订版3查询:
WITH
pg_namespace AS (
SELECT
nspname
, nspowner
, rtrim(ltrim(array_to_string(nspacl, ','), '{'), '}') as nspacl
FROM pg_catalog.pg_namespace
WHERE nspname = 'public'
),
-- Generating a table with the numbers 1 - 10 in a single column.
ten_numbers AS (
SELECT
1 AS num
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 0
),
-- Expands the values in ten_numbers to create a single column with the values 1 - 10,000.
depivot_index AS (
SELECT
(1000 * t1.num) + (100 * t2.num) + (10 * t3.num) + t4.num AS gen_num
FROM ten_numbers AS t1
JOIN ten_numbers AS t2 ON 1 = 1
JOIN ten_numbers AS t3 ON 1 = 1
JOIN ten_numbers AS t4 ON 1 = 1
),
-- Filters down generated_numbers to house only the numbers up to the maximum times that the delimiter appears.
splitter AS (
SELECT
*
FROM depivot_index
WHERE gen_num BETWEEN 1 AND (
SELECT max(REGEXP_COUNT(nspacl, '\\,') + 1)
FROM pg_namespace
)
),
-- Cross joins permissions_groups and splitter to populate all requests, delimited on ','.
expanded_input AS (
SELECT
pg.nspname
, pg.nspacl
, trim(split_part(pg.nspacl, ',', s.gen_num)) AS raw_permissions_string
FROM pg_namespace AS pg
JOIN splitter AS s ON 1 = 1
WHERE split_part(nspacl, ',', s.gen_num) <> ''
),
-- Breaks out the owner and grantee fields into their own columns respectively.
users_with_raw_permissions_data AS (
SELECT
e.raw_permissions_string
, e.nspname
, trim(split_part(e.raw_permissions_string, '=', 1)) AS grantee
, trim(split_part(trim(split_part(e.raw_permissions_string, '=', 2)), '/', 2)) AS owner
, trim(split_part(trim(split_part(e.raw_permissions_string, '=', 2)), '/', 1)) AS raw_permissions_data
FROM
expanded_input e
),
-- Mines privilege types from raw string data.
access_privilege_types AS (
SELECT
u.nspname
, u.owner
, u.grantee
,CASE
WHEN position('C*' IN u.raw_permissions_data) > 0 THEN 'C*'
WHEN position('U*' IN u.raw_permissions_data) > 0 THEN 'U*'
WHEN position('C' IN u.raw_permissions_data) > 0 THEN 'C'
WHEN position('U' IN u.raw_permissions_data) > 0 THEN 'U'
ELSE u.raw_permissions_data
END AS first_access_privilege
, CASE
WHEN position('U*' IN u.raw_permissions_data) > 0 THEN 'U*'
WHEN position('C*' IN u.raw_permissions_data) > 0 THEN 'C*'
WHEN position('U' IN u.raw_permissions_data) > 0 THEN 'U'
WHEN position('C' IN u.raw_permissions_data) > 0 THEN 'C'
ELSE u.raw_permissions_data
END AS second_access_privilege
, first_access_privilege || ',' || second_access_privilege AS merged_access_privileges
FROM users_with_raw_permissions_data u
),
-- Cross joins access_privilge_types and splitter to populate all privilege_types, delimited on ','.
expanded_access_privilege_types AS (
SELECT
a.nspname
, a.owner
, a.grantee
, trim(split_part(a.merged_access_privileges, ',', s.gen_num)) AS access_privileges
FROM access_privilege_types AS a
JOIN splitter AS s ON 1 = 1
WHERE split_part(a.merged_access_privileges, ',', s.gen_num) <> ''
GROUP BY 1, 2, 3, 4
)
SELECT
ea.nspname
, ea.owner
, ea.grantee
, LEFT(ea.access_privileges, 1) AS access_privilege
, CASE
WHEN POSITION('*' IN ea.access_privileges) > 0 THEN 'YES'
ELSE 'NO'
END AS is_grantable
FROM expanded_access_privilege_types ea
ORDER BY 1, 2, 3, 4, 5
编辑#4:
添加一些关于ten_numbers
,depivot_index
和splitter
表如何分解pg_catalog.pg_namespace.nspacl
字段的说明。总体概述是ten_numbers
和depivot_index are created purely to return tables with numbered rows to use as an index when joining in the
split_part values of
nspacl`。
ten_numbers
生成一个具有单个列的表,其中包含数字0-9:
------- | num | ------- | 0 | ------- | 1 | ------- | etc | ------- | 9 | -------
然后在CTE depivot_index
期间扩展此表以容纳范围0-9999:
----------- | gen_num | ----------- | 0 | ----------- | 1 | ----------- | 2 | ----------- | etc | ----------- | 9998 | ----------- | 9999 | -----------
splitter
然后缩小表格范围,只容纳nspacl
字段中指定分隔符的最大数目以下的数字:
------- | num | ------- | 0 | ------- | 1 | ------- | etc | ------- | 6 | -------
然后splitter
返回的表通过CTE CROSS JOIN
中1 = 1
上的联接用作expanded_input
的目标。这样可以确保split_part
返回的每个成员都有自己的行:
--------------------------------------------------------------------------- | nspname | nspacl | raw_permissions_string | --------------------------------------------------------------------------- | avengers | "{james=UC/james,adam=C/james}" | "james=UC/james" | --------------------------------------------------------------------------- | avengers | "{james=UC/james,adam=C/james}" | "adam=C/james" | --------------------------------------------------------------------------- | avengers | etc. | etc. | ---------------------------------------------------------------------------