summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThong Kuah <tkuah@gitlab.com>2019-07-04 11:10:31 +1200
committerThong Kuah <tkuah@gitlab.com>2019-07-08 09:47:40 +1200
commitd80ae904b72afedc6391d9a2bef65d661dbd7a2e (patch)
tree6146d50d0353f02a3922211c40463282a914b48d
parent9c606487f0d3b1883d06bdbd03088f1892b3f3f1 (diff)
downloadgitlab-ce-clusters-group-cte.tar.gz
Improve ClustersHierarchy based on BE feedbackclusters-group-cte
-rw-r--r--app/models/clusters/clusters_hierarchy.rb92
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)