summaryrefslogtreecommitdiff
path: root/app/finders/issuable_finder.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/finders/issuable_finder.rb')
-rw-r--r--app/finders/issuable_finder.rb67
1 files changed, 46 insertions, 21 deletions
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 93bef592c65..b73a3fa6e01 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -14,7 +14,9 @@
# project_id: integer
# milestone_title: string
# author_id: integer
+# author_username: string
# assignee_id: integer or 'None' or 'Any'
+# assignee_username: string
# search: string
# label_name: string
# sort: string
@@ -25,12 +27,13 @@
# created_before: datetime
# updated_after: datetime
# updated_before: datetime
-# use_cte_for_search: boolean
+# attempt_group_search_optimizations: boolean
#
class IssuableFinder
prepend FinderWithCrossProjectAccess
include FinderMethods
include CreatedAtFilter
+ include Gitlab::Utils::StrongMemoize
requires_cross_project_access unless: -> { project? }
@@ -49,25 +52,15 @@ class IssuableFinder
assignee_username
author_id
author_username
- authorized_only
- group_id
- iids
label_name
milestone_title
my_reaction_emoji
- non_archived
- project_id
- scope
search
- sort
- state
- include_subgroups
- use_cte_for_search
]
end
def self.array_params
- @array_params ||= { label_name: [], iids: [], assignee_username: [] }
+ @array_params ||= { label_name: [], assignee_username: [] }
end
def self.valid_params
@@ -83,8 +76,9 @@ class IssuableFinder
items = init_collection
items = filter_items(items)
- # This has to be last as we may use a CTE as an optimization fence by
- # passing the use_cte_for_search param
+ # This has to be last as we may use a CTE as an optimization fence
+ # by passing the attempt_group_search_optimizations param and
+ # enabling the use_cte_for_group_issues_search feature flag
# https://www.postgresql.org/docs/current/static/queries-with.html
items = by_search(items)
@@ -93,6 +87,8 @@ class IssuableFinder
def filter_items(items)
items = by_project(items)
+ items = by_group(items)
+ items = by_subquery(items)
items = by_scope(items)
items = by_created_at(items)
items = by_updated_at(items)
@@ -218,7 +214,14 @@ class IssuableFinder
end
def filter_by_no_label?
- labels? && params[:label_name].include?(Label::None.title)
+ downcased = label_names.map(&:downcase)
+
+ # Label::NONE is deprecated and should be removed in 12.0
+ downcased.include?(FILTER_NONE) || downcased.include?(Label::NONE)
+ end
+
+ def filter_by_any_label?
+ label_names.map(&:downcase).include?(FILTER_ANY)
end
def labels
@@ -283,12 +286,31 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ def use_subquery_for_search?
+ strong_memoize(:use_subquery_for_search) do
+ attempt_group_search_optimizations? &&
+ Feature.enabled?(:use_subquery_for_group_issues_search, default_enabled: false)
+ end
+ end
+
+ def use_cte_for_search?
+ strong_memoize(:use_cte_for_search) do
+ attempt_group_search_optimizations? &&
+ !use_subquery_for_search? &&
+ Feature.enabled?(:use_cte_for_group_issues_search, default_enabled: true)
+ end
+ end
+
private
def init_collection
klass.all
end
+ def attempt_group_search_optimizations?
+ search && Gitlab::Database.postgresql? && params[:attempt_group_search_optimizations]
+ end
+
def count_key(value)
Array(value).last.to_sym
end
@@ -352,12 +374,13 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def use_cte_for_search?
- return false unless search
- return false unless Gitlab::Database.postgresql?
- return false unless Feature.enabled?(:use_cte_for_group_issues_search, default_enabled: true)
-
- params[:use_cte_for_search]
+ # Wrap projects and groups in a subquery if the conditions are met.
+ def by_subquery(items)
+ if use_subquery_for_search?
+ klass.where(id: items.select(:id)) # rubocop: disable CodeReuse/ActiveRecord
+ else
+ items
+ end
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -473,6 +496,8 @@ class IssuableFinder
items =
if filter_by_no_label?
items.without_label
+ elsif filter_by_any_label?
+ items.any_label
else
items.with_label(label_names, params[:sort])
end