diff options
author | Thong Kuah <tkuah@gitlab.com> | 2019-07-04 11:10:31 +1200 |
---|---|---|
committer | Thong Kuah <tkuah@gitlab.com> | 2019-07-08 09:47:40 +1200 |
commit | d80ae904b72afedc6391d9a2bef65d661dbd7a2e (patch) | |
tree | 6146d50d0353f02a3922211c40463282a914b48d | |
parent | 9c606487f0d3b1883d06bdbd03088f1892b3f3f1 (diff) | |
download | gitlab-ce-clusters-group-cte.tar.gz |
Improve ClustersHierarchy based on BE feedbackclusters-group-cte
-rw-r--r-- | app/models/clusters/clusters_hierarchy.rb | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/app/models/clusters/clusters_hierarchy.rb b/app/models/clusters/clusters_hierarchy.rb index 79fc916d7ce..dab034b7234 100644 --- a/app/models/clusters/clusters_hierarchy.rb +++ b/app/models/clusters/clusters_hierarchy.rb @@ -4,8 +4,6 @@ module Clusters class ClustersHierarchy DEPTH_COLUMN = :depth - attr_reader :clusterable - def initialize(clusterable) @clusterable = clusterable end @@ -13,76 +11,90 @@ module Clusters # Returns clusters in order from deepest to highest group def base_and_ancestors cte = recursive_cte - cte_alias = cte.table.alias(Clusters::Cluster.table_name) + cte_alias = cte.table.alias(model.table_name) - Clusters::Cluster + model .unscoped .where('clusters.id IS NOT NULL') .with .recursive(cte.to_arel) .from(cte_alias) - .order(depth: :asc) + .order(DEPTH_COLUMN => :asc) end private + attr_reader :clusterable + def recursive_cte cte = Gitlab::SQL::RecursiveCTE.new(:clusters_cte) - cte << base_query(clusterable) + base_query = case clusterable + when ::Group + group_clusters_base_query + when ::Project + project_clusters_base_query + else + raise ArgumentError, "unknown type for #{clusterable}" + end + + cte << base_query + cte << parent_query(cte) + cte + end + + def group_clusters_base_query group_parent_id_alias = alias_as_column(groups[:parent_id], 'group_parent_id') - parent_query = Clusters::Cluster + join_sources = ::Group.left_joins(:clusters).join_sources + + model + .unscoped + .select([clusters_star, group_parent_id_alias, "1 AS #{DEPTH_COLUMN}"]) + .where(groups[:id].eq(clusterable.id)) + .from(groups) + .joins(join_sources) + end + + def project_clusters_base_query + projects = ::Project.arel_table + project_parent_id_alias = alias_as_column(projects[:namespace_id], 'group_parent_id') + join_sources = ::Project.left_joins(:clusters).join_sources + + model + .unscoped + .select([clusters_star, project_parent_id_alias, "1 AS #{DEPTH_COLUMN}"]) + .where(projects[:id].eq(clusterable.id)) + .from(projects) + .joins(join_sources) + end + + def parent_query(cte) + group_parent_id_alias = alias_as_column(groups[:parent_id], 'group_parent_id') + + model .unscoped .select([clusters_star, group_parent_id_alias, cte.table[DEPTH_COLUMN] + 1]) .from([cte.table, groups]) .joins('LEFT OUTER JOIN cluster_groups ON cluster_groups.group_id = namespaces.id') .joins('LEFT OUTER JOIN clusters ON cluster_groups.cluster_id = clusters.id') .where(groups[:id].eq(cte.table[:group_parent_id])) - - cte << parent_query - - cte end - def base_query(clusterable) - case clusterable - when ::Group - group_parent_id_alias = alias_as_column(groups[:parent_id], 'group_parent_id') - join_sources = ::Group.left_joins(:clusters).join_sources - - Clusters::Cluster - .unscoped - .select([clusters_star, group_parent_id_alias, "1 AS #{DEPTH_COLUMN}"]) - .where(groups[:id].eq(clusterable.id)) - .from(groups) - .joins(join_sources) - when ::Project - projects = ::Project.arel_table - project_parent_id_alias = alias_as_column(projects[:namespace_id], 'group_parent_id') - join_sources = ::Project.left_joins(:clusters).join_sources - - Clusters::Cluster - .unscoped - .select([clusters_star, project_parent_id_alias, "1 AS #{DEPTH_COLUMN}"]) - .where(projects[:id].eq(clusterable.id)) - .from(projects) - .joins(join_sources) - else - raise ArgumentError, "unknown type for #{clusterable}" - end + def model + Clusters::Cluster end def clusters - Clusters::Cluster.arel_table + @clusters ||= model.arel_table end def groups - ::Group.arel_table + @groups ||= ::Group.arel_table end def clusters_star - clusters[Arel.star] + @clusters_star ||= clusters[Arel.star] end def alias_as_column(value, alias_to) |