diff --git a/common/djangoapps/django_comment_common/models.py b/common/djangoapps/django_comment_common/models.py index 0d27aa9a07efe8c49386dd2128733adf19683f15..a0b48c4c2feef5ee74d1b114f3a80f0a08e0de7e 100644 --- a/common/djangoapps/django_comment_common/models.py +++ b/common/djangoapps/django_comment_common/models.py @@ -145,13 +145,25 @@ def all_permissions_for_user_in_course(user, course_id): # pylint: disable=inva if course is None: raise ItemNotFoundError(course_id) - all_roles = {role.name for role in Role.objects.filter(users=user, course_id=course_id)} + all_roles = {role for role in Role.objects.filter(users=user, course_id=course_id)} + role_names = {role.name for role in all_roles} + + # TODO: EDUCATOR-3374 + # The `roles__users__roles__in=all_roles` part of this filter is a hack to get the new + # Aurora MySql query planner to properly use the unique index on the roles/users join table. + # Without this hack, the planner uses a unique index on (role_id, user_id) to do lookup + # by user_id only, which is a completely inefficient way to use that index. + permission_queryset = Permission.objects.filter( + roles__users=user, + roles__course_id=course_id, + roles__users__roles__in=all_roles + ).distinct() permissions = { permission.name for permission - in Permission.objects.filter(roles__users=user, roles__course_id=course_id) - if not permission_blacked_out(course, all_roles, permission.name) + in permission_queryset + if not permission_blacked_out(course, role_names, permission.name) } return permissions diff --git a/lms/djangoapps/courseware/tests/test_discussion_xblock.py b/lms/djangoapps/courseware/tests/test_discussion_xblock.py index 10b8bbacd5a8244052fead02e6a2090df252d4a3..d57267d4cc5878e98b15ee34d0dc9a5417d623c5 100644 --- a/lms/djangoapps/courseware/tests/test_discussion_xblock.py +++ b/lms/djangoapps/courseware/tests/test_discussion_xblock.py @@ -402,11 +402,13 @@ class TestXBlockQueryLoad(SharedModuleStoreTestCase): discussion_target='Target Discussion', )) - # 3 queries are required to do first discussion xblock render: + # 2 queries are required to do first discussion xblock render: # * django_comment_client_role - # * django_comment_client_permission # * lms_xblock_xblockasidesconfig - num_queries = 3 + # If the query for roles returned a non-empty result set, there would be + # an additional query against django_comment_client_permission, but there + # are no roles associated with this test. + num_queries = 2 for discussion in discussions: discussion_xblock = get_module_for_descriptor_internal( user=user,