Skip to content

Commit 5685eda

Browse files
authored
feat(query): add is_role_in_session funciton (#19867)
1 parent 78092fc commit 5685eda

2 files changed

Lines changed: 146 additions & 0 deletions

File tree

src/query/sql/src/planner/semantic/type_check/sugar.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ impl<'a> TypeChecker<'a> {
5454
Ascii::new("current_role"),
5555
Ascii::new("current_secondary_roles"),
5656
Ascii::new("current_available_roles"),
57+
Ascii::new("is_role_in_session"),
5758
Ascii::new("connection_id"),
5859
Ascii::new("client_session_id"),
5960
Ascii::new("timezone"),
@@ -181,6 +182,49 @@ impl<'a> TypeChecker<'a> {
181182
)))),
182183
}
183184
}
185+
("is_role_in_session", &[role]) => {
186+
let effective_roles = match self.ctx.get_all_effective_roles().await {
187+
Ok(roles) => roles,
188+
Err(err) => return Some(Err(err)),
189+
};
190+
let (role_expr, _) = match self.resolve(role) {
191+
Ok(res) => *res,
192+
Err(err) => return Some(Err(err)),
193+
};
194+
195+
let mut predicate_levels =
196+
Vec::with_capacity(effective_roles.len().max(1).ilog2() as usize + 1);
197+
for effective_role in effective_roles {
198+
let role_literal = ScalarExpr::ConstantExpr(ConstantExpr {
199+
span,
200+
value: Scalar::String(effective_role.name),
201+
});
202+
let predicate =
203+
match self.resolve_scalar_function_call(span, "eq", vec![], vec![
204+
role_expr.clone(),
205+
role_literal,
206+
]) {
207+
Ok(res) => {
208+
let (predicate, _) = *res;
209+
predicate
210+
}
211+
Err(err) => return Some(Err(err)),
212+
};
213+
if let Err(err) = self.merge_or_level(span, &mut predicate_levels, predicate) {
214+
return Some(Err(err));
215+
}
216+
}
217+
218+
let predicate = match self.fold_or_levels(span, predicate_levels) {
219+
Ok(Some(predicate)) => predicate,
220+
Ok(None) => ScalarExpr::ConstantExpr(ConstantExpr {
221+
span,
222+
value: Scalar::Boolean(false),
223+
}),
224+
Err(err) => return Some(Err(err)),
225+
};
226+
Some(self.resolve_scalar_function_call(span, "is_true", vec![], vec![predicate]))
227+
}
184228
("connection_id", &[]) => Some(self.resolve(&Expr::Literal {
185229
span,
186230
value: Literal::String(self.ctx.get_connection_id()),

tests/sqllogictests/suites/ee/05_ee_ddl/05_0004_ddl_security_policy.test

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,5 +1063,107 @@ DROP TABLE employees;
10631063
statement ok
10641064
DROP MASKING POLICY mask_ssn_conditional;
10651065

1066+
## row access policy with active role hierarchy
1067+
statement ok
1068+
SET ROLE account_admin;
1069+
1070+
statement ok
1071+
SET SECONDARY ROLES ALL;
1072+
1073+
statement ok
1074+
DROP TABLE IF EXISTS rap_time_range_test;
1075+
1076+
statement ok
1077+
DROP ROW ACCESS POLICY IF EXISTS rap_time_range;
1078+
1079+
statement ok
1080+
DROP ROLE IF EXISTS rap_role_7_day;
1081+
1082+
statement ok
1083+
DROP ROLE IF EXISTS rap_role_1_day;
1084+
1085+
statement ok
1086+
CREATE ROLE rap_role_7_day;
1087+
1088+
statement ok
1089+
CREATE ROLE rap_role_1_day;
1090+
1091+
statement ok
1092+
CREATE ROW ACCESS POLICY rap_time_range AS (start_time TIMESTAMP) RETURNS boolean ->
1093+
CASE
1094+
WHEN IS_ROLE_IN_SESSION('rap_role_7_day') THEN
1095+
start_time BETWEEN to_timestamp('2024-01-08 00:00:00') AND to_timestamp('2024-01-15 00:00:00')
1096+
WHEN IS_ROLE_IN_SESSION('rap_role_1_day') THEN
1097+
start_time BETWEEN to_timestamp('2024-01-14 00:00:00') AND to_timestamp('2024-01-15 00:00:00')
1098+
ELSE false
1099+
END;
1100+
1101+
statement ok
1102+
CREATE TABLE rap_time_range_test(id INT, start_time TIMESTAMP);
1103+
1104+
statement ok
1105+
INSERT INTO rap_time_range_test VALUES
1106+
(1, to_timestamp('2024-01-07 00:00:00')),
1107+
(2, to_timestamp('2024-01-09 00:00:00')),
1108+
(3, to_timestamp('2024-01-14 12:00:00')),
1109+
(4, to_timestamp('2024-01-15 00:00:00')),
1110+
(5, to_timestamp('2024-01-16 00:00:00'));
1111+
1112+
statement ok
1113+
ALTER TABLE rap_time_range_test ADD ROW ACCESS POLICY rap_time_range ON (start_time);
1114+
1115+
statement ok
1116+
SET ROLE rap_role_1_day;
1117+
1118+
statement ok
1119+
SET SECONDARY ROLES NONE;
1120+
1121+
query I
1122+
SELECT id FROM rap_time_range_test ORDER BY id;
1123+
----
1124+
3
1125+
4
1126+
1127+
statement ok
1128+
SET SECONDARY ROLES rap_role_7_day;
1129+
1130+
query I
1131+
SELECT id FROM rap_time_range_test ORDER BY id;
1132+
----
1133+
2
1134+
3
1135+
4
1136+
1137+
statement ok
1138+
SET ROLE rap_role_7_day;
1139+
1140+
statement ok
1141+
SET SECONDARY ROLES NONE;
1142+
1143+
query I
1144+
SELECT id FROM rap_time_range_test ORDER BY id;
1145+
----
1146+
2
1147+
3
1148+
4
1149+
1150+
statement ok
1151+
SET ROLE account_admin;
1152+
1153+
statement ok
1154+
SET SECONDARY ROLES ALL;
1155+
1156+
statement ok
1157+
DROP TABLE rap_time_range_test;
1158+
1159+
statement ok
1160+
DROP ROW ACCESS POLICY rap_time_range;
1161+
1162+
statement ok
1163+
DROP ROLE rap_role_7_day;
1164+
1165+
statement ok
1166+
DROP ROLE rap_role_1_day;
1167+
10661168
statement ok
10671169
unset global enable_planner_cache;

0 commit comments

Comments
 (0)