-- -- Slightly faster (around 10%) versions for the base permission query functions. -- In the new versions the lookup of acs__magic_object_id was moved out of the loop. -- -- -- procedure acs_permission__permission_p/3 -- DROP FUNCTION IF EXISTS acs_permission__permission_p(integer, integer, varchar); CREATE OR REPLACE FUNCTION acs_permission__permission_p( permission_p__object_id integer, permission_p__party_id integer, permission_p__privilege varchar ) RETURNS boolean AS $$ DECLARE v_security_context_root integer; BEGIN v_security_context_root := acs__magic_object_id('security_context_root'); RETURN EXISTS (WITH RECURSIVE object_context(object_id, context_id) AS ( SELECT permission_p__object_id, permission_p__object_id FROM acs_objects WHERE object_id = permission_p__object_id UNION ALL SELECT ao.object_id, CASE WHEN (ao.security_inherit_p = 'f' OR ao.context_id IS NULL) THEN v_security_context_root ELSE ao.context_id END FROM object_context oc, acs_objects ao WHERE ao.object_id = oc.context_id AND ao.object_id != v_security_context_root ), privilege_ancestors(privilege, child_privilege) AS ( SELECT permission_p__privilege, permission_p__privilege UNION ALL SELECT aph.privilege, aph.child_privilege FROM privilege_ancestors pa JOIN acs_privilege_hierarchy aph ON aph.child_privilege = pa.privilege ) SELECT 1 FROM acs_permissions p JOIN party_approved_member_map pap ON pap.party_id = p.grantee_id JOIN privilege_ancestors pa ON pa.privilege = p.privilege JOIN object_context oc ON p.object_id = oc.context_id WHERE pap.member_id = permission_p__party_id ); END; $$ LANGUAGE plpgsql stable; -- for tsearch -- -- procedure acs_permission__permission_p_recursive_array/3 -- DROP FUNCTION IF EXISTS acs_permission__permission_p_recursive_array(integer[], integer, varchar); CREATE OR REPLACE FUNCTION acs_permission__permission_p_recursive_array( permission_p__objects integer[], permission_p__party_id integer, permission_p__privilege varchar ) RETURNS table (object_id integer, orig_object_id integer) AS $$ DECLARE v_security_context_root integer; BEGIN v_security_context_root := acs__magic_object_id('security_context_root'); RETURN QUERY WITH RECURSIVE object_context(obj_id, context_id, orig_obj_id) AS ( SELECT unnest(permission_p__objects), unnest(permission_p__objects), unnest(permission_p__objects) UNION ALL SELECT ao.object_id, CASE WHEN (ao.security_inherit_p = 'f' OR ao.context_id IS NULL) THEN v_security_context_root ELSE ao.context_id END, oc.orig_obj_id FROM object_context oc, acs_objects ao WHERE ao.object_id = oc.context_id AND ao.object_id != v_security_context_root ), privilege_ancestors(privilege, child_privilege) AS ( SELECT permission_p__privilege, permission_p__privilege UNION ALL SELECT aph.privilege, aph.child_privilege FROM privilege_ancestors pa JOIN acs_privilege_hierarchy aph ON aph.child_privilege = pa.privilege ) SELECT p.object_id, oc.orig_obj_id FROM acs_permissions p JOIN party_approved_member_map pap ON pap.party_id = p.grantee_id JOIN privilege_ancestors pa ON pa.privilege = p.privilege JOIN object_context oc ON p.object_id = oc.context_id WHERE pap.member_id = permission_p__party_id; END; $$ LANGUAGE plpgsql stable;