uqa_sql/catalog/roles/
inquiry.rs1use super::{
10 guards::RoleCatalogGuards,
11 memberships::{
12 parse_pg_has_role_privileges, pg_has_role_privilege, resolve_pg_has_role_identifier,
13 role_privilege_text,
14 },
15 RoleReferenceNames,
16};
17use crate::catalog::roles::RoleReference;
18use crate::SQLError;
19use uqa_core::Value;
20
21pub fn pg_has_role_value(
22 names: &dyn RoleReferenceNames,
23 catalog: &dyn RoleCatalogGuards,
24 arguments: &[Value],
25) -> Result<Value, SQLError> {
26 if arguments.iter().any(|argument| argument == &Value::Null) {
27 return Ok(Value::Null);
28 }
29 let (subject_value, target_value, privilege_value) = match arguments {
30 [target, privilege] => (None, target, privilege),
31 [subject, target, privilege] => (Some(subject), target, privilege),
32 _ => {
33 return Err(SQLError::BadArity {
34 name: "pg_has_role".into(),
35 expected: "2 or 3".into(),
36 actual: arguments.len(),
37 });
38 }
39 };
40 let current_user = subject_value.is_none().then(|| names.current_role());
41 let roles = catalog.role_definitions();
42 let subject = subject_value.map_or_else(
43 || Ok(current_user),
44 |value| {
45 resolve_pg_has_role_identifier(value, &roles).map(|role| role.map(RoleReference::from))
46 },
47 )?;
48 let target = resolve_pg_has_role_identifier(target_value, &roles)?;
49 let privileges = parse_pg_has_role_privileges(role_privilege_text(privilege_value)?)?;
50 let memberships = catalog.role_memberships();
51 let allowed = privileges.into_iter().any(|privilege| {
52 pg_has_role_privilege(
53 &roles,
54 &memberships,
55 subject.as_ref(),
56 target.as_deref(),
57 privilege,
58 )
59 });
60 Ok(Value::Bool(allowed))
61}