Commit e520a946 authored by Andreas Brandl's avatar Andreas Brandl

Merge branch '47988-improve-milestone-queries-with-subq' into 'master'

Improve MilestonesFinder to accept project and group relations

Closes #47988

See merge request gitlab-org/gitlab-ce!24325
parents 8547b546 2f76ff19
...@@ -144,7 +144,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -144,7 +144,7 @@ class Projects::MilestonesController < Projects::ApplicationController
def search_params def search_params
if request.format.json? && project_group && can?(current_user, :read_group, project_group) if request.format.json? && project_group && can?(current_user, :read_group, project_group)
groups = project_group.self_and_ancestors_ids groups = project_group.self_and_ancestors.select(:id)
end end
params.permit(:state).merge(project_ids: @project.id, group_ids: groups) params.permit(:state).merge(project_ids: @project.id, group_ids: groups)
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
# Search for milestones # Search for milestones
# #
# params - Hash # params - Hash
# project_ids: Array of project ids or single project id. # project_ids: Array of project ids or single project id or ActiveRecord relation.
# group_ids: Array of group ids or single group id. # group_ids: Array of group ids or single group id or ActiveRecord relation.
# order - Orders by field default due date asc. # order - Orders by field default due date asc.
# title - filter by title. # title - filter by title.
# state - filters by state. # state - filters by state.
...@@ -12,17 +12,13 @@ ...@@ -12,17 +12,13 @@
class MilestonesFinder class MilestonesFinder
include FinderMethods include FinderMethods
attr_reader :params, :project_ids, :group_ids attr_reader :params
def initialize(params = {}) def initialize(params = {})
@project_ids = Array(params[:project_ids])
@group_ids = Array(params[:group_ids])
@params = params @params = params
end end
def execute def execute
return Milestone.none if project_ids.empty? && group_ids.empty?
items = Milestone.all items = Milestone.all
items = by_groups_and_projects(items) items = by_groups_and_projects(items)
items = by_title(items) items = by_title(items)
...@@ -34,7 +30,7 @@ class MilestonesFinder ...@@ -34,7 +30,7 @@ class MilestonesFinder
private private
def by_groups_and_projects(items) def by_groups_and_projects(items)
items.for_projects_and_groups(project_ids, group_ids) items.for_projects_and_groups(params[:project_ids], params[:group_ids])
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -45,7 +45,7 @@ class Milestone < ActiveRecord::Base ...@@ -45,7 +45,7 @@ class Milestone < ActiveRecord::Base
groups = groups.compact if groups.is_a? Array groups = groups.compact if groups.is_a? Array
groups = [] if groups.nil? groups = [] if groups.nil?
where(project: projects).or(where(group: groups)) where(project_id: projects).or(where(group_id: groups))
end end
scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) } scope :order_by_name_asc, -> { order(Arel::Nodes::Ascending.new(arel_table[:title].lower)) }
...@@ -191,7 +191,7 @@ class Milestone < ActiveRecord::Base ...@@ -191,7 +191,7 @@ class Milestone < ActiveRecord::Base
return STATE_COUNT_HASH unless projects || groups return STATE_COUNT_HASH unless projects || groups
counts = Milestone counts = Milestone
.for_projects_and_groups(projects&.map(&:id), groups&.map(&:id)) .for_projects_and_groups(projects, groups)
.reorder(nil) .reorder(nil)
.group(:state) .group(:state)
.count .count
...@@ -275,8 +275,7 @@ class Milestone < ActiveRecord::Base ...@@ -275,8 +275,7 @@ class Milestone < ActiveRecord::Base
if project if project
relation = Milestone.for_projects_and_groups([project_id], [project.group&.id]) relation = Milestone.for_projects_and_groups([project_id], [project.group&.id])
elsif group elsif group
project_ids = group.projects.map(&:id) relation = Milestone.for_projects_and_groups(group.projects.select(:id), [group.id])
relation = Milestone.for_projects_and_groups(project_ids, [group.id])
end end
title_exists = relation.find_by_title(title) title_exists = relation.find_by_title(title)
......
...@@ -61,10 +61,10 @@ class IssuableBaseService < BaseService ...@@ -61,10 +61,10 @@ class IssuableBaseService < BaseService
return unless milestone_id return unless milestone_id
params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE params[:milestone_id] = '' if milestone_id == IssuableFinder::NONE
group_ids = project.group&.self_and_ancestors&.pluck(:id) groups = project.group&.self_and_ancestors&.select(:id)
milestone = milestone =
Milestone.for_projects_and_groups([project.id], group_ids).find_by_id(milestone_id) Milestone.for_projects_and_groups([project.id], groups).find_by_id(milestone_id)
params[:milestone_id] = '' unless milestone params[:milestone_id] = '' unless milestone
end end
......
...@@ -82,11 +82,9 @@ module Milestones ...@@ -82,11 +82,9 @@ module Milestones
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def group_project_ids def group_project_ids
@group_project_ids ||= group.projects.pluck(:id) group.projects.select(:id)
end end
# rubocop: enable CodeReuse/ActiveRecord
def raise_error(message) def raise_error(message)
raise PromoteMilestoneError, "Promotion failed - #{message}" raise PromoteMilestoneError, "Promotion failed - #{message}"
......
...@@ -14,7 +14,7 @@ module Projects ...@@ -14,7 +14,7 @@ module Projects
order: { due_date: :asc, title: :asc } order: { due_date: :asc, title: :asc }
} }
finder_params[:group_ids] = @project.group.self_and_ancestors_ids if @project.group finder_params[:group_ids] = @project.group.self_and_ancestors.select(:id) if @project.group
MilestonesFinder.new(finder_params).execute.select([:iid, :title]) MilestonesFinder.new(finder_params).execute.select([:iid, :title])
end end
......
---
title: Improve milestone queries using subqueries instead of separate queries for ids
merge_request: 24325
author:
type: performance
...@@ -101,9 +101,9 @@ module Banzai ...@@ -101,9 +101,9 @@ module Banzai
def self_and_ancestors_ids(parent) def self_and_ancestors_ids(parent)
if group_context?(parent) if group_context?(parent)
parent.self_and_ancestors_ids parent.self_and_ancestors.select(:id)
elsif project_context?(parent) elsif project_context?(parent)
parent.group&.self_and_ancestors_ids parent.group&.self_and_ancestors&.select(:id)
end end
end end
......
...@@ -286,8 +286,8 @@ describe Milestone do ...@@ -286,8 +286,8 @@ describe Milestone do
end end
context 'relations as params' do context 'relations as params' do
let(:projects) { Project.where(id: project.id) } let(:projects) { Project.where(id: project.id).select(:id) }
let(:groups) { Group.where(id: group.id) } let(:groups) { Group.where(id: group.id).select(:id) }
it_behaves_like 'filters by projects and groups' it_behaves_like 'filters by projects and groups'
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment