投影策略¶
本主题介绍如何使用投影策略,允许或阻止在 SQL 查询结果的最终输出中投影列。
概述¶
A projection policy is a first-class, schema-level object that defines whether a column can be projected in the output of a SQL query result. A column with a projection policy assigned to it is said to be projection constrained. Projection policies can be used to constrain sensitive or private information (for example, name or phone number) when sharing data securely between partners.
然而,请注意,被投影策略隐藏的列仍然可以在内部查询或 WHERE 子句中使用,这可能会泄露有关给定字段的信息。有关更多详细信息,请参阅 注意事项 部分(本主题内容)。
创建投影策略后,策略管理员可以将投影策略分配给列。在任何时候,只能为一列分配一个投影策略。只有当用户的活动角色符合允许投影列的投影策略条件时,用户才能投影列。
请注意,投影约束列也可以受掩码策略保护,并且包含投影约束列的表可以受行访问策略保护。有关更多详细信息,请参阅 :ref:`label-projection_policy_masking_rap`(本主题内容)。
投影策略仅影响最终结果表中可见的列。因此,当“protected_C”列拒绝投影时,运行以下查询的用户将看到 NULL,如下所示:
SELECT protected_C, -- NULL, in outer query
my_func(protected_C), -- Any functions on NULL returns NULL
nonprotected_C
FROM (SELECT protected_C, -- Projection policies are ignored in a nested query.
nonprotected_C from T)
WHERE protected_C > 5; -- Not shown in results, so this works
列使用情况¶
Snowflake 会跟踪列的使用情况。当对列设置了投影策略时,对列的间接引用(例如视图定义、UDF [本主题内容] 和常用表表达式)会影响列的投影。
当对列设置了投影策略,但列无法被投影时,则该列:
不包含在查询结果的输出中。
不能插入到其他表。
不能作为外部函数或存储过程的实参。
限制¶
注意事项¶
当用例要求查询敏感列而不直接向分析师或类似角色公开列值时,可使用投影策略。与屏蔽值或标记化值相比,可以更灵活地分析投影约束列内的列值。但是,在对列设置投影策略之前,请考虑以下事项:
投影策略不会阻止对个人的操作。
例如,用户可以筛选
name
列对应特定个人的行,即使该列受投影约束。但是,用户无法运行 SELECT 语句查看表中个人的姓名。当投影约束列在将受保护表中的数据与未受保护表中的数据合并在一起的查询中用作联接键时,没有任何限制能够阻止用户在未受保护表中投影该列的值。因此,如果未受保护表中的值与受保护列的值匹配,用户可以通过从未受保护表中投影来获取该值。
例如,假设已为
t_protected
表的email
列分配了投影策略。用户仍然可以通过执行以下操作确定t_protected.email
列中的值:SELECT t_unprotected.email FROM t_unprotected JOIN t_protected ON t_unprotected.email = t_protected.email;
投影约束不能保证恶意行为者无法通过故意查询来从投影约束列中获取可能敏感的数据。投影策略最适合用于已有一定信任度的合作伙伴和客户。此外,提供商应警惕可能存在的数据滥用(例如,查看列表的访问历史记录)。
在少数情况下,包含投影约束列的查询的错误消息可能包含该列中的单个值。
出于以上原因,如果需要防止关于特定列或实体的信息泄漏,应当从数据中彻底省略该列,或采用 差分隐私。
创建投影策略¶
投影策略包含一个调用 PROJECTION_CONSTRAINT 函数的 body
,以确定是否对列进行投影。
CREATE OR REPLACE PROJECTION POLICY <name> AS () RETURNS PROJECTION_CONSTRAINT -> <body>其中:
name
指定策略的名称。
AS () RETURNS PROJECTION_CONSTRAINT
是策略的签名和返回类型。签名不接受任何实参,返回类型为 PROJECTION_CONSTRAINT,这是一种内部数据类型。所有投影策略都具有相同的签名和返回类型。
body
是确定是否对列进行投影的 SQL 表达式。这可以包括 CASE 和其他有效 SQL 语句,也可以包括计算结果为 TRUE 或 FALSE 的 SELECT 子句。不要返回 NULL 以禁止投影。 您必须返回带有值的 PROJECTION_CONSTRAINT 函数,指定是否允许对指定列进行投影,以及如何处理请求该列的查询。请参阅 CREATE PROJECTION POLICY 以了解语法。
策略示例¶
最简单的投影策略直接调用 PROJECTION_CONSTRAINT 函数:
- 允许列投影
CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => true);
- 阻止列投影
CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => false);
- 防止列投影到特定角色
可以编写更复杂的 SQL 表达式来调用 PROJECTION_CONSTRAINT 函数。表达式可以使用 条件表达式函数 和 上下文函数 来引入逻辑,允许具有特定角色的某些用户投影列,并阻止所有其他用户投影列。
小技巧
在条件策略中使用上下文函数时,可以使用以下策略:
上下文函数返回字符串,因此使用它们进行比较时区分大小写。如果想进行不区分大小写的比较,可以使用 LOWER 将字符串转换为全部小写。
当上下文函数返回某个值时,POLICY_CONTEXT 函数可以帮助您评估策略正文是否返回正确的值。POLICY_CONTEXT 函数根据一个或多个上下文函数的指定值模拟查询结果。
以下示例包括一个 CASE 表达式和 CURRENT_ROLE 上下文函数,用于创建一个条件策略,该策略仅允许具有
analyst
自定义角色的用户投影列:CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN CURRENT_ROLE() = 'ANALYST' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
下一个示例允许具有
analyst
角色的用户访问该列,但其他任何人只能看到该列的或源自该列的任何列的 NULL 值。CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN CURRENT_ROLE() = 'ANALYST' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false, ENFORCEMENT => 'NULLIFY') END;
- 在投影策略中使用标签:
以下示例使用 SYSTEM$GET_TAG_ON_CURRENT_COLUMN 函数,这样分配给列的标记就可以确定是否可以投影该列。在这种情况下,当策略分配给一列时,该列上的
tags.accounting_col
标记值必须为public
,才能投影该列。CREATE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN SYSTEM$GET_TAG_ON_CURRENT_COLUMN('tags.accounting_col') = 'public' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
对于数据共享用例,提供商可以编写投影策略,使用 CURRENT_ACCOUNT 上下文函数限制所有使用者账户的列投影,或使用 INVOKER_SHARE 上下文函数有选择地限制特定共享中的列投影。例如:
- 限制所有使用者账户
在此示例中,
provider.account
是账户名称格式的 账户标识符:CREATE OR REPLACE PROJECTION POLICY restrict_consumer_accounts AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN CURRENT_ACCOUNT() = 'provider.account' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
- 限制到特定共享
假设有一个数据共享提供商账户,它在安全视图的一列上设置了投影策略。有两个不同的共享(
SHARE1
和SHARE2
)可以访问安全视图,以支持两个不同的数据共享使用者。如果数据共享使用者账户中的用户尝试通过任一共享方式进行列投影,则他们可以投影该列;否则无法进行投影。
CREATE OR REPLACE PROJECTION POLICY projection_share AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN INVOKER_SHARE() IN ('SHARE1', 'SHARE2') THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
- 查询一个单独的表以确定投影策略
您可以在策略逻辑中使用 SELECT 查询,来帮助确定是否允许或阻止投影。如果以这种方式查询表(映射表),我们建议将映射表放在与受保护的表相同的数据库中。如果
body
部分调用 IS_DATABASE_ROLE_IN_SESSION,则这一点尤为重要。以下是一个扩展示例,展示了如何创建和填充角色名称和投影权限的简单映射表,然后查询该表以确定根据用户的角色,某列是否可以投影到当前用户。
-- Create mapping table with two columns: role name, whether that role can project the column CREATE OR REPLACE TABLE roles_with_access(role string, allowed boolean) AS SELECT * FROM VALUES ('ACCOUNTADMIN', true), ('RANDOM_ROLE', false); -- Create a policy that queries the mapping table, and allows projection when current -- user role has an `allowed` value of TRUE. -- Note that the logic is written to default to FALSE in all other cases, including the -- current role not being in the queried table. CREATE OR REPLACE PROJECTION POLICY pp AS () RETURNS projection_constraint -> CASE WHEN exists( SELECT 1 FROM roles_with_access WHERE role = current_role() AND allowed = true ) THEN projection_constraint(ALLOW=>true) ELSE projection_constraint(ALLOW=>false) END; -- Create a new table with the policy and query it in one step. CREATE OR REPLACE TABLE t(user string, address string WITH PROJECTION POLICY pp) AS SELECT * FROM VALUES ('Carson', 'CA'), ('Emily', 'NY'), ('John', 'NV'); -- Succeeds USE ROLE ACCOUNTADMIN; SELECT * FROM t; -- Fails with projection policy error on column ADDRESS USE ROLE any_other_role; SELECT * FROM t;
分配投影策略¶
使用 ALTER TABLE ...ALTER COLUMN 命令可将投影策略应用于表列,使用 ALTER VIEW 命令可将投影策略应用于视图列。每列仅支持一个投影策略。
ALTER { TABLE | VIEW } <name> { ALTER | MODIFY } COLUMN <col1_name> SET PROJECTION POLICY <policy_name> [ FORCE ] [ , <col2_name> SET PROJECTION POLICY <policy_name> [ FORCE ] ... ]
其中:
name
指定表或视图的名称。col1_name
指定表或视图中列的名称。col2_name
指定表或视图中附加列的名称。policy_name
指定在列上设置的投影策略的名称。FORCE
是一个可选参数,该参数允许命令将投影策略分配给已分配了投影策略的列。新的投影策略会以原子方式替换现有的投影策略。
例如,在表的 account_number
列上设置投影策略 proj_policy_acctnumber
:
ALTER TABLE finance.accounting.customers MODIFY COLUMN account_number SET PROJECTION POLICY proj_policy_acctnumber;
您还可以使用 CREATE TABLE 和 CREATE VIEW 命令的 WITH 子句,在创建表或视图时为列分配投影策略。例如,要将策略 my_proj_policy
分配给新表的 account_number
列,请执行:
CREATE TABLE t1 (account_number NUMBER WITH PROJECTION POLICY my_proj_policy);
在现有表中添加新列时,也可以使用 WITH 子句。例如,要将策略 my_proj_policy
分配给 zipcode
列(该列正在被添加到现有表 customers
中),请执行:
ALTER TABLE customers ADD COLUMN account_number NUMBER WITH PROJECTION POLICY my_proj_policy;
替换投影策略¶
替换投影策略的推荐方法是使用 FORCE
参数分离现有投影策略,并在一条命令中分配新的投影策略。这使您能够以原子方式替换旧策略,而不会留下任何保护漏洞。
例如,要为已受投影约束的列分配新的投影策略,请执行以下语句:
ALTER TABLE finance.accounting.customers
MODIFY COLUMN account_number
SET PROJECTION POLICY proj_policy2 FORCE;
您也可以在一条语句 (...UNSET PROJECTION POLICY) 中分离列的投影策略,然后在另一条语句 (...SET PROJECTION POLICY <name>) 中为列设置新的策略。如果选择此方法,在分离一个策略和分配另一个策略之间,列不受投影策略的保护。在此期间,查询可能会访问敏感数据。
分离投影策略¶
使用 ALTER TABLE 或 ALTER VIEW 命令中的 UNSET PROJECTION POLICY 子句,可以从表或视图的列中分离投影策略。投影策略的名称不是必需的,因为一列不能附加多个投影策略。
ALTER { TABLE | VIEW } <name> { ALTER | MODIFY } COLUMN <col1_name> UNSET PROJECTION POLICY [ , <col2_name> UNSET PROJECTION POLICY ... ]
其中:
name
指定表或视图的名称。col1_name
指定表或视图中列的名称。col2_name
指定表或视图中附加列的名称。
例如,要移除 account_number
列中的投影策略,请执行以下语句:
ALTER TABLE finance.accounting.customers MODIFY COLUMN account_number UNSET PROJECTION POLICY;
使用 Snowsight 查看投影策略¶
要确定列是否有投影策略,请执行以下操作:
Sign in to Snowsight.
In the navigation menu, select Catalog » Database Explorer, and then navigate to the table that contains the column.
选择 Columns 选项卡。
使用 Policy 列,以确定该列是否有任何数据治理策略。
将鼠标悬停在每个策略上,以确定它是否为投影策略。
如果是投影策略,您还可以确定投影策略是阻止查询执行还是返回输出中的 NULL 值。如果策略的正文很复杂并且在不同条件下的行为不同,则 Snowsight 显示正文的内容,而不是简单地说明查询是失败还是返回 NULL 值。
使用 SQL 监控投影策略¶
实用做法是,考虑采用两种通用方法来确定如何监控投影策略的使用情况。
了解投影策略¶
您可以在共享 SNOWFLAKE 数据库的 Account Usage 架构中使用 PROJECTION_POLICIES 视图。此视图是 Snowflake 账户中所有投影策略的 目录。例如:
SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.PROJECTION_POLICIES ORDER BY POLICY_NAME;
识别投影策略引用¶
POLICY_REFERENCES Information Schema 表函数可以识别投影策略引用。有两种不同的语法选项:
为在列上设置了指定投影策略的每个对象(即,表或视图)返回一行:
USE DATABASE my_db; SELECT policy_name, policy_kind, ref_entity_name, ref_entity_domain, ref_column_name, ref_arg_column_names, policy_status FROM TABLE(information_schema.policy_references(policy_name => 'my_db.my_schema.projpolicy'));
为分配给名为
my_table
的表的每个策略返回一行:USE DATABASE my_db; USE SCHEMA information_schema; SELECT policy_name, policy_kind, ref_entity_name, ref_entity_domain, ref_column_name, ref_arg_column_names, policy_status FROM TABLE(information_schema.policy_references(ref_entity_name => 'my_db.my_schema.my_table', ref_entity_domain => 'table'));
扩展示例¶
创建投影策略并为列分配投影策略的一般步骤与创建和分配其他策略(如掩码策略和行访问策略)的步骤相同:
对于集中式管理方法,可创建自定义角色(例如
proj_policy_admin
)来管理策略。授予此角色创建和分配投影策略的权限。
创建投影策略。
将投影策略分配给列。
根据此通用程序,完成以下步骤为列分配投影策略:
创建自定义角色以管理投影策略:
USE ROLE useradmin; CREATE ROLE proj_policy_admin;
授予
proj_policy_admin
自定义角色相应权限,以便在架构中创建投影策略并将投影策略分配给 Snowflake 账户中的任何表或视图列。此步骤假定投影策略将存储在名为
privacy.projpolicies
的数据库和架构中,并且此数据库和架构已存在:GRANT USAGE ON DATABASE privacy TO ROLE proj_policy_admin; GRANT USAGE ON SCHEMA privacy.projpolicies TO ROLE proj_policy_admin; GRANT CREATE PROJECTION POLICY ON SCHEMA privacy.projpolicies TO ROLE proj_policy_admin; GRANT APPLY PROJECTION POLICY ON ACCOUNT TO ROLE proj_policy_admin;
有关详细信息,请参阅 :ref:`label-projection_policy_manage`(本主题内容)。
创建投影策略以阻止列投影:
USE ROLE proj_policy_admin; USE SCHEMA privacy.projpolicies; CREATE OR REPLACE PROJECTION POLICY proj_policy_false AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => false);
将投影策略分配给表列:
ALTER TABLE customers MODIFY COLUMN active SET PROJECTION POLICY privacy.projpolicies.proj_policy_false;
投影策略与 Snowflake 功能¶
以下小节简要总结了投影策略如何与各种 Snowflake 功能和服务交互。
掩码和行访问策略¶
- 多种策略:
一列可以同时具有掩码策略和投影策略,并且包含此列的表可以受行访问策略的保护。如果这三个策略都存在,Snowflake 将按如下方式处理表和策略:
根据行访问策略应用行筛选器。
确定查询是否正在尝试投影受投影策略限制的任何列,如果是,则拒绝查询。
根据掩码策略应用列掩码。
受掩码策略保护的列也可以受到投影约束。例如,在包含账号的列上设置的掩码策略可以具有一个条件,允许具有
finance_admin
自定义角色的用户查看账号;同时具有另一个条件,对于所有其他角色,将账号替换为哈希。投影策略可以进一步限制列,使具有
analyst
自定义角色的用户无法投影列。请注意,具有analyst
自定义角色的用户仍可通过对哈希进行分组或联接这些哈希来分析列。Snowflake 建议策略管理员与内部合规性和监管人员合作,确定应对哪些列进行投影约束。
- 策略评估:
在以下情况下,掩码策略或行访问策略无法引用投影约束列:
为表分配行访问策略。
在 条件掩码策略 中枚举一个或多个列。
执行映射表查找。
如 label-projection_limitations`(本主题内容)中所述,投影策略 :samp:`{body} 不能引用受掩码策略保护的列或受行访问策略保护的表。
采用其他投影策略的依赖对象¶
请考虑以下一系列对象:
base_table
»v1
»v2
其中:
v1
是基于名为base_table
的表创建的视图。
v2
是基于v1
构建的视图。
如果对视图中受投影约束的某个列进行查询,而该列又依赖于 base_table
中受投影约束的列,则只有当 两个 投影策略都允许对该列进行投影时,才会对视图列进行投影。
Snowflake 会检查列沿袭(一直到基表),以确保对列的任何引用都不受投影约束。如果沿袭链中的任何列受投影约束,并且不允许投影该列,则 Snowflake 将阻止查询。
视图和物化视图¶
视图列上的投影策略约束的是视图列,而不是基表列。
关于引用,约束表列的投影策略将延续到引用受约束表列的视图。
流和任务¶
表中列的投影策略会延续到同一个表上的流。请注意,不能在流上设置投影策略。
同样,当任务引用受约束的列时,受投影约束的列仍受约束。
UNPIVOT¶
UNPIVOT 结构的结果取决于列最初是否受投影策略的约束。注意:
执行 UNPIVOT 之前和之后,受约束的列仍受投影约束。
name_column
始终显示在查询结果中。如果
column_list
中的任何列受投影约束,那么value_column
也受投影约束。
克隆对象¶
以下方法有助于保护数据,防止拥有 SELECT 权限的用户访问存储在克隆数据库或架构中的克隆表或视图:
不支持克隆单个投影策略对象。
克隆架构会导致克隆该架构中的所有投影策略。
克隆的表会映射到与源表相同的投影策略。
当表在其父架构克隆的上下文中进行克隆时,如果源表引用了同一父架构中的投影策略(即本地引用),则克隆的表将引用克隆的投影策略。
如果源表引用了不同架构中的投影策略(即外部引用),则克隆的表会保留外部引用。
有关更多信息,请参阅 CREATE <object> ... CLONE。
复制¶
可以使用数据库复制和复制组来复制投影策略及其分配情况。
对于 数据库复制,如果满足以下任一条件,则复制操作会失败:
主数据库位于 Enterprise(或更高版本)账户中,包含策略,但批准复制的一个或多个账户所属的版本较低。
主数据库中包含的表或视图可以 悬空引用 到其他数据库中的投影策略。
在 复制组 中复制多个数据库时,可避免数据库复制的悬空引用行为。
用户定义的函数 (UDFs)¶
请注意以下有关投影约束和 UDFs 的内容:
- Scalar SQL UDFs:
Snowflake 会评估 UDF,然后将投影策略应用于投影约束列。
如果 SELECT 语句中的一列是从派生自投影约束列的 UDF 传递派生的,则 Snowflake 会阻止查询。换言之:
pc_column
» UDF » 列(在 SELECT 语句中)其中:
pc_column
指投影约束列。
因为 SELECT 语句中的列可追溯到投影约束列,因此 Snowflake 会阻止查询。
- SQL UDTFs:
SQL 用户定义的表函数 (UDTF) 遵循与 SQL UDFs 相同的行为,但由于在函数输出中会返回行,因此 Snowflake 会独立评估表中的每一列,以决定是否在函数输出中投影该列。
- 其他 UDFs:
以下内容适用于 Java UDFs 简介、JavaScript UDFs 简介 和 Python UDFs 简介:
投影约束列在 UDTF 输出中受到约束。
- 日志记录和事件表:
当 UDF、UDTF 或 JavaScript UDF 具有投影约束实参时,Snowflake 不会在相应的事件表中捕获日志记录和事件详细信息。但是,Snowflake 允许 UDF/UDTF 执行,并且不会由于日志记录原因导致调用 UDF/UDTF 的语句失败。
权限和命令¶
以下各小节提供有助于管理投影策略的信息。
投影策略权限¶
Snowflake 支持对投影策略对象的以下权限。
要对架构中的任何对象执行操作,需要对父数据库和架构的 USAGE 权限。请注意,如果某个角色获授某个架构的任意权限,该角色便能够解析该架构。例如,若某角色被授予 CREATE 权限,则可以在该架构上创建对象,而无需 同时 被授予该架构的 USAGE 权限。
权限 |
用途 |
---|---|
APPLY |
允许在列上对投影策略执行设置和设置操作。 |
OWNERSHIP |
转移投影策略的所有权,从而授予对投影策略的完全控制权。更改投影策略的大多数属性时需要此权限。 |
有关详细信息,请参阅 :ref:`label-projection_policy_ddl_privilege_summary`(本主题内容)。
投影策略 DDL 引用¶
Snowflake 支持通过以下 DDL 创建和管理投影策略。
DDL 命令、操作和权限总结¶
下表总结了投影策略权限和 DDL 操作之间的关系。
要对架构中的任何对象执行操作,需要对父数据库和架构的 USAGE 权限。请注意,如果某个角色获授某个架构的任意权限,该角色便能够解析该架构。例如,若某角色被授予 CREATE 权限,则可以在该架构上创建对象,而无需 同时 被授予该架构的 USAGE 权限。
操作 |
所需权限 |
---|---|
创建投影策略。 |
在同一架构中具有 CREATE PROJECTION POLICY 权限的角色。 |
更改投影策略。 |
对投影策略具有 OWNERSHIP 权限的角色。 |
描述投影策略 |
以下其中一项:
|
弃用投影策略。 |
对投影策略具有 OWNERSHIP 权限的角色。 |
显示投影策略。 |
以下其中一项:
|
在列上设置或取消设置投影策略。 |
以下其中一项:
|
Snowflake 支持不同的权限,以创建和设置对象的投影策略。
对于集中式投影策略管理方法,即
projection_policy_admin
自定义角色对 所有 列创建和设置投影策略时采用的方法,需要以下权限:USE ROLE securityadmin; GRANT USAGE ON DATABASE mydb TO ROLE projection_policy_admin; GRANT USAGE ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT CREATE PROJECTION POLICY ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT APPLY ON PROJECTION POLICY ON ACCOUNT TO ROLE projection_policy_admin;
在混合管理方法中,单个角色具有 CREATE PROJECTION POLICY 权限,以确保投影策略的命名一致,并且各个团队或角色具有特定投影策略的 APPLY 权限。
例如,可以向自定义角色
finance_role
授予在角色拥有的表和视图(即该角色对表或视图具有 OWNERSHIP 权限)上设置投影策略cost_center
的权限:USE ROLE securityadmin; GRANT CREATE PROJECTION POLICY ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT APPLY ON PROJECTION POLICY cost_center TO ROLE finance_role;