创建行策略,即一种用于确定用户可从表中读取哪些行的过滤器。
语法:
-- Multiple names on one table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name [, ...]
[ON CLUSTER cluster_name]
ON { [db.]table | db.* }
[IN access_storage_type]
[FOR SELECT] USING condition
[AS {PERMISSIVE | RESTRICTIVE}]
[TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]
-- One name on multiple table targets
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name
[ON CLUSTER cluster_name]
ON { [db.]table | db.* } [, ...]
[IN access_storage_type]
[FOR SELECT] USING condition
[AS {PERMISSIVE | RESTRICTIVE}]
[TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]
-- Mixed packing: each name paired with its own table target
CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE]
policy_name ON { [db.]table | db.* } [, policy_name ON { [db.]table | db.* } ...]
[ON CLUSTER cluster_name]
[IN access_storage_type]
[FOR SELECT] USING condition
[AS {PERMISSIVE | RESTRICTIVE}]
[TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]ParserRowPolicyNames 支持三种打包形式 (并非完整的笛卡尔积) :
- 多个名称,一个目标 —
pol1, pol2 ON table1会在该表 (或db.*) 上创建列出的每个名称。 - 一个名称,多个目标 —
pol1 ON table1, table2会在每个列出的目标上创建相同的短名称。 - 混合配对 —
p1 ON t1, p2 ON t2仅在各自配对的目标上创建对应的名称。
多名称列表不能与多表 ON 列表组合在同一组中:p1, p2 ON t1, t2 会被拒绝。多名称组之后,也不能在同一语句中追加另一个以逗号分隔的 name ON target 组。
可选的 ON CLUSTER 适用于整个语句 (仅指定一个集群名称) 。ClickHouse 不接受在单个创建语句中为每个策略名称指定不同的 ON CLUSTER — 若必须在不同集群上创建策略,请分别执行 CREATE ROW POLICY 语句。
多个名称和表
有效:
-- Several policy names, one table
CREATE ROW POLICY pol1, pol2, pol3 ON table1
FOR SELECT USING id = 1
TO accountant;
-- One policy name, several tables
CREATE ROW POLICY IF NOT EXISTS pol1 ON table1, table2, table3
FOR SELECT USING id = 1
TO accountant;
-- Mixed packing: different name per table
CREATE ROW POLICY p4 ON db.table, p5 ON db2.table2
USING a = b;
-- Same policy on several tables, on a cluster
CREATE ROW POLICY IF NOT EXISTS pol1 ON CLUSTER replicated_cluster ON table1, table2
FOR SELECT USING id = 1
TO accountant;无效:
-- Multi-name × multi-table in one ON-group (not a Cartesian product)
CREATE ROW POLICY p1, p2 ON t1, t2
FOR SELECT USING id = 1
TO accountant;
-- Different clusters per name in one statement
CREATE ROW POLICY pol1 ON CLUSTER cluster1 ON table1, pol2 ON CLUSTER cluster2 ON table2USING 子句
允许指定用于过滤行的条件。若某一行上的该条件计算结果非零,用户就能看到该行。
TO 子句
在 TO 部分中,您可以指定此策略适用的用户和 roles 列表。例如,CREATE ROW POLICY ... TO accountant, john@localhost。
关键字 ALL 表示所有 ClickHouse 用户,包括当前用户。关键字 ALL EXCEPT 允许从所有用户列表中排除某些用户,例如 CREATE ROW POLICY ... TO ALL EXCEPT accountant, john@localhost
AS 子句
允许同一用户在同一张表上同时启用多个策略。因此,我们需要一种方式来组合多个策略中的条件。
默认情况下,策略通过布尔 OR 运算符进行组合。例如,以下策略:
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 TO peter, antonio允许用户 peter 查看满足 b=1 或 c=2 的行。
AS 子句指定策略应如何与其他策略组合。策略可以是宽松型或限制型。默认情况下,策略为宽松型,这意味着它们会通过布尔 OR 运算符组合。
或者,也可以将策略定义为限制型。限制型策略会通过布尔 AND 运算符组合。
以下是通用公式:
row_is_visible = (one or more of the permissive policies' conditions are non-zero) AND
(all of the restrictive policies's conditions are non-zero)例如,以下策略:
CREATE ROW POLICY pol1 ON mydb.table1 USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio仅当 b=1 且 c=2 两个条件同时满足时,才允许用户 peter 查看这些行。
数据库策略会与表策略组合生效。
例如,以下策略:
CREATE ROW POLICY pol1 ON mydb.* USING b=1 TO mira, peter
CREATE ROW POLICY pol2 ON mydb.table1 USING c=2 AS RESTRICTIVE TO peter, antonio使用户 peter 只有在同时满足 b=1 且 c=2 时才能看到 table1 的行,尽管
mydb 中的任何其他表对该用户都只会应用 b=1 策略。
Distributed 和由远程服务器支持的表
行策略会在实际读取表数据的位置过滤行。将读取操作委托给远程服务器的表,例如 Distributed 表或其封装 (例如,目标为 Distributed 的 materialized view) ,只会将查询文本发送到远程服务器,无法对远程读取应用策略过滤器。为避免过滤器被悄然忽略,策略适用用户对这类表发起的查询会因 ILLEGAL_PREWHERE 错误而被拒绝。
请改为在每台远程服务器的底层本地表上定义策略;当发送的查询读取这些表时,策略会在该处生效:
-- Filters reads of local_table on this server, including reads shipped by a Distributed table over it.
CREATE ROW POLICY filter ON mydb.local_table USING a < 1000 TO john;ON CLUSTER 子句
允许在集群中创建行策略,参见 Distributed DDL。这也是在集群中每台服务器的本地表上创建策略的便捷方式。
示例
CREATE ROW POLICY filter1 ON mydb.mytable USING a<1000 TO accountant, john@localhost
CREATE ROW POLICY filter2 ON mydb.mytable USING a<1000 AND b=5 TO ALL EXCEPT mira
CREATE ROW POLICY filter3 ON mydb.mytable USING 1 TO admin
CREATE ROW POLICY filter4 ON mydb.* USING 1 TO admin