summaryrefslogtreecommitdiff
path: root/app/models/namespaces/traversal/linear.rb
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /app/models/namespaces/traversal/linear.rb
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
downloadgitlab-ce-aee0a117a889461ce8ced6fcf73207fe017f1d99.tar.gz
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/models/namespaces/traversal/linear.rb')
-rw-r--r--app/models/namespaces/traversal/linear.rb38
1 files changed, 37 insertions, 1 deletions
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index 1736fe82ca5..5a5f2a5d063 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -64,6 +64,13 @@ module Namespaces
traversal_ids.present?
end
+ def use_traversal_ids_for_ancestors_upto?
+ return false unless use_traversal_ids?
+ return false unless Feature.enabled?(:use_traversal_ids_for_ancestors_upto, root_ancestor, default_enabled: :yaml)
+
+ traversal_ids.present?
+ end
+
def use_traversal_ids_for_root_ancestor?
return false unless Feature.enabled?(:use_traversal_ids_for_root_ancestor, default_enabled: :yaml)
@@ -114,6 +121,35 @@ module Namespaces
hierarchy_order == :desc ? traversal_ids[0..-2] : traversal_ids[0..-2].reverse
end
+ # Returns all ancestors upto but excluding the top.
+ # When no top is given, all ancestors are returned.
+ # When top is not found, returns all ancestors.
+ #
+ # This copies the behavior of the recursive method. We will deprecate
+ # this behavior soon.
+ def ancestors_upto(top = nil, hierarchy_order: nil)
+ return super unless use_traversal_ids_for_ancestors_upto?
+
+ # We can't use a default value in the method definition above because
+ # we need to preserve those specific parameters for super.
+ hierarchy_order ||= :desc
+
+ # Get all ancestor IDs inclusively between top and our parent.
+ top_index = top ? traversal_ids.find_index(top.id) : 0
+ ids = traversal_ids[top_index...-1]
+ ids_string = ids.map { |id| Integer(id) }.join(',')
+
+ # WITH ORDINALITY lets us order the result to match traversal_ids order.
+ from_sql = <<~SQL
+ unnest(ARRAY[#{ids_string}]::bigint[]) WITH ORDINALITY AS ancestors(id, ord)
+ INNER JOIN namespaces ON namespaces.id = ancestors.id
+ SQL
+
+ self.class
+ .from(Arel.sql(from_sql))
+ .order('ancestors.ord': hierarchy_order)
+ end
+
def self_and_ancestors(hierarchy_order: nil)
return super unless use_traversal_ids_for_ancestors?
@@ -168,7 +204,7 @@ module Namespaces
end
if bottom
- skope = skope.where(id: bottom.traversal_ids[0..-1])
+ skope = skope.where(id: bottom.traversal_ids)
end
# The original `with_depth` attribute in ObjectHierarchy increments as you