diff options
author | Toon Claes <toon@gitlab.com> | 2017-05-30 22:06:38 +0200 |
---|---|---|
committer | Toon Claes <toon@gitlab.com> | 2017-05-31 10:12:39 +0200 |
commit | a52b54f3dae8a161050c31f45de900f4d59985e7 (patch) | |
tree | c548341d138d30672643fac4f3a83b7406964b3d | |
parent | 3ea9de81f2789093317eb583364059414f1ab6bc (diff) | |
download | gitlab-ce-a52b54f3dae8a161050c31f45de900f4d59985e7.tar.gz |
Optimize query for User#groups_through_project_authorizationstc-fix-group-finder-subgrouping-9-2
Instead of plucking paths, and doing LIKE/OR on each of them, use a subquery to
find groups that are the ancestor of the projects the user is member of.
-rw-r--r-- | app/models/user.rb | 17 | ||||
-rw-r--r-- | spec/finders/groups_finder_spec.rb | 2 |
2 files changed, 9 insertions, 10 deletions
diff --git a/app/models/user.rb b/app/models/user.rb index e2d840a1fe0..157e0948cd3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -493,15 +493,14 @@ class User < ActiveRecord::Base end def groups_through_project_authorizations - paths = Project.member_self_and_descendants(id).pluck('routes.path') - - return Group.none if paths.empty? - - wheres = paths.map do |path| - "#{ActiveRecord::Base.connection.quote(path)} LIKE CONCAT(routes.path, '/%')" - end - - Group.joins(:route).where(wheres.join(' OR ')) + projects = Project.joins(:project_authorizations). + where('project_authorizations.user_id = ?', id ). + joins(:route). + select('routes.path AS full_path') + + Group.joins(:route). + joins("INNER JOIN (#{projects.to_sql}) project_paths + ON project_paths.full_path LIKE CONCAT(routes_namespaces.path, '/%')") end def nested_groups diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb index 31f1f753d4d..e082631ce68 100644 --- a/spec/finders/groups_finder_spec.rb +++ b/spec/finders/groups_finder_spec.rb @@ -91,7 +91,7 @@ describe GroupsFinder do subsubproject = create(:empty_project, :private, namespace: private_subsubgroup) subsubproject.add_guest(user) - is_expected.to include(private_subsubgroup) + expect(described_class.new(user).execute).to include(private_subsubgroup, private_subgroup, parent_group) end end end |