From d8e504a8f790f032f5d7757c6d61093faa7a2542 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Wed, 11 Oct 2017 18:24:11 +0200 Subject: Use Arel to build preloaded counts --- app/models/concerns/loaded_in_group_list.rb | 93 ++++++++++++++--------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb index 4c4045fdab2..3dacfdf92e7 100644 --- a/app/models/concerns/loaded_in_group_list.rb +++ b/app/models/concerns/loaded_in_group_list.rb @@ -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 -- cgit v1.2.1