summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2018-03-13 18:09:07 +0100
committerBob Van Landuyt <bob@vanlanduyt.co>2018-03-13 18:09:07 +0100
commit6fdcf5af89115fb7db3378c065162d2107a21183 (patch)
tree7b8d8ce5e824680758c70bc95feeedad5932a63b
parent9a1af4a39c79067574c6e96a61d25e5463f10b56 (diff)
downloadgitlab-ce-bvl-optimize-owned-projects-query.tar.gz
Use `EXISTS` to load projects from owned groupsbvl-optimize-owned-projects-query
This should be more efficient than the old `namespace_id IN` query.
-rw-r--r--app/models/user.rb15
-rw-r--r--spec/models/user_spec.rb4
2 files changed, 15 insertions, 4 deletions
diff --git a/app/models/user.rb b/app/models/user.rb
index b8c55205ab8..c896b7be78d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -5,6 +5,7 @@ class User < ActiveRecord::Base
include Gitlab::ConfigHelper
include Gitlab::SQL::Pattern
+ include Gitlab::Utils::StrongMemoize
include AfterCommitQueue
include Avatarable
include Referable
@@ -98,7 +99,7 @@ class User < ActiveRecord::Base
# Groups
has_many :members
- has_many :group_members, -> { where(requested_at: nil) }, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil) }
has_many :groups, through: :group_members
has_many :owned_groups, -> { where members: { access_level: Gitlab::Access::OWNER } }, through: :group_members, source: :group
has_many :masters_groups, -> { where members: { access_level: Gitlab::Access::MASTER } }, through: :group_members, source: :group
@@ -623,9 +624,15 @@ class User < ActiveRecord::Base
end
def owned_projects
- @owned_projects ||=
- Project.where('namespace_id IN (?) OR namespace_id = ?',
- owned_groups.select(:id), namespace.id).joins(:namespace)
+ strong_memoize(:owned_projects) do
+ group_owned = group_members
+ .where(access_level: Gitlab::Access::OWNER)
+ .where("projects.namespace_id = members.source_id")
+ .select(1)
+
+ Project.where('namespace_id = ? OR EXISTS (?)',
+ namespace.id, group_owned)
+ end
end
# Returns projects which user can admin issues on (for example to move an issue to that project).
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5680eb24985..bd0a0c0158c 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -661,6 +661,8 @@ describe User do
describe 'projects' do
before do
@user = create(:user)
+ owned_group = create(:group)
+ owned_group.add_owner(@user)
@project = create(:project, namespace: @user.namespace)
@project_2 = create(:project, group: create(:group)) do |project|
@@ -669,6 +671,7 @@ describe User do
@project_3 = create(:project, group: create(:group)) do |project|
project.add_developer(@user)
end
+ @project_4 = create(:project, group: owned_group)
end
it { expect(@user.authorized_projects).to include(@project) }
@@ -677,6 +680,7 @@ describe User do
it { expect(@user.owned_projects).to include(@project) }
it { expect(@user.owned_projects).not_to include(@project_2) }
it { expect(@user.owned_projects).not_to include(@project_3) }
+ it { expect(@user.owned_projects).to include(@project_4) }
it { expect(@user.personal_projects).to include(@project) }
it { expect(@user.personal_projects).not_to include(@project_2) }
it { expect(@user.personal_projects).not_to include(@project_3) }