Use Arel to build preloaded counts

This commit is contained in:
Bob Van Landuyt 2017-10-11 18:24:11 +02:00
parent 18907efbc9
commit d8e504a8f7
1 changed files with 45 additions and 48 deletions

View File

@ -1,47 +1,56 @@
module LoadedInGroupList
extend ActiveSupport::Concern
PROJECT_COUNT_SQL = <<~PROJECTCOUNT.freeze
SELECT COUNT(*) AS preloaded_project_count
FROM projects
WHERE projects.namespace_id = namespaces.id
PROJECTCOUNT
SUBGROUP_COUNT_SQL = <<~SUBGROUPCOUNT.freeze
(SELECT COUNT(*) AS preloaded_subgroup_count
FROM namespaces children
WHERE children.parent_id = namespaces.id)
SUBGROUPCOUNT
MEMBER_COUNT_SQL = <<~MEMBERCOUNT.freeze
(SELECT COUNT(*) AS preloaded_member_count
FROM members
WHERE members.source_type = 'Namespace'
AND members.source_id = namespaces.id
AND members.requested_at IS NULL)
MEMBERCOUNT
COUNT_SELECTS = ['namespaces.*',
SUBGROUP_COUNT_SQL,
MEMBER_COUNT_SQL].freeze
module ClassMethods
def with_counts(archived:)
selects = COUNT_SELECTS.dup << project_count(archived)
select(selects)
selects_including_counts = [
'namespaces.*',
"(#{project_count_sql(archived).to_sql})",
"(#{subgroup_count_sql.to_sql})",
"(#{member_count_sql.to_sql})"
]
select(selects_including_counts)
end
def with_selects_for_list(archived: nil)
with_route.with_counts(archived: archived)
end
def project_count(archived)
project_count = if archived == 'only'
PROJECT_COUNT_SQL + 'AND projects.archived IS true'
elsif Gitlab::Utils.to_boolean(archived)
PROJECT_COUNT_SQL
else
PROJECT_COUNT_SQL + 'AND projects.archived IS NOT true'
end
"(#{project_count})"
private
def project_count_sql(archived = nil)
projects = Project.arel_table
namespaces = Namespace.arel_table
base_count = projects.project(Arel.star.count.as('preloaded_project_count'))
.where(projects[:namespace_id].eq(namespaces[:id]))
if archived == 'only'
base_count.where(projects[:archived].eq(true))
elsif Gitlab::Utils.to_boolean(archived)
base_count
else
base_count.where(projects[:archived].not_eq(true))
end
end
def subgroup_count_sql
namespaces = Namespace.arel_table
children = namespaces.alias('children')
namespaces.project(Arel.star.count.as('preloaded_subgroup_count'))
.from(children)
.where(children[:parent_id].eq(namespaces[:id]))
end
def member_count_sql
members = Member.arel_table
namespaces = Namespace.arel_table
members.project(Arel.star.count.as('preloaded_member_count'))
.where(members[:source_type].eq(Namespace.name))
.where(members[:source_id].eq(namespaces[:id]))
.where(members[:requested_at].eq(nil))
end
end
@ -50,26 +59,14 @@ module LoadedInGroupList
end
def project_count
@project_count ||= if respond_to?(:preloaded_project_count)
preloaded_project_count
else
projects.non_archived.count
end
@project_count ||= try(:preloaded_project_count) || projects.non_archived.count
end
def subgroup_count
@subgroup_count ||= if respond_to?(:preloaded_subgroup_count)
preloaded_subgroup_count
else
children.count
end
@subgroup_count ||= try(:preloaded_subgroup_count) || children.count
end
def member_count
@member_count ||= if respond_to?(:preloaded_member_count)
preloaded_member_count
else
users.count
end
@member_count ||= try(:preloaded_member_count) || users.count
end
end