Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /app/models/namespaces/traversal
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/models/namespaces/traversal')
-rw-r--r--app/models/namespaces/traversal/linear.rb38
-rw-r--r--app/models/namespaces/traversal/linear_scopes.rb29
-rw-r--r--app/models/namespaces/traversal/recursive.rb1
3 files changed, 55 insertions, 13 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
diff --git a/app/models/namespaces/traversal/linear_scopes.rb b/app/models/namespaces/traversal/linear_scopes.rb
index f5c44171c42..0dfb7320461 100644
--- a/app/models/namespaces/traversal/linear_scopes.rb
+++ b/app/models/namespaces/traversal/linear_scopes.rb
@@ -105,27 +105,32 @@ module Namespaces
:traversal_ids,
'LEAD (namespaces.traversal_ids, 1) OVER (ORDER BY namespaces.traversal_ids ASC) next_traversal_ids'
)
- cte = Gitlab::SQL::CTE.new(:base_cte, base)
+ base_cte = Gitlab::SQL::CTE.new(:descendants_base_cte, base)
namespaces = Arel::Table.new(:namespaces)
- records = unscoped
- .with(cte.to_arel)
- .from([cte.table, namespaces])
# Bound the search space to ourselves (optional) and descendants.
#
# WHERE (base_cte.next_traversal_ids IS NULL OR base_cte.next_traversal_ids > namespaces.traversal_ids)
# AND next_traversal_ids_sibling(base_cte.traversal_ids) > namespaces.traversal_ids
- records = records
- .where(cte.table[:next_traversal_ids].eq(nil).or(cte.table[:next_traversal_ids].gt(namespaces[:traversal_ids])))
- .where(next_sibling_func(cte.table[:traversal_ids]).gt(namespaces[:traversal_ids]))
+ records = unscoped
+ .from([base_cte.table, namespaces])
+ .where(base_cte.table[:next_traversal_ids].eq(nil).or(base_cte.table[:next_traversal_ids].gt(namespaces[:traversal_ids])))
+ .where(next_sibling_func(base_cte.table[:traversal_ids]).gt(namespaces[:traversal_ids]))
# AND base_cte.traversal_ids <= namespaces.traversal_ids
- if include_self
- records.where(cte.table[:traversal_ids].lteq(namespaces[:traversal_ids]))
- else
- records.where(cte.table[:traversal_ids].lt(namespaces[:traversal_ids]))
- end
+ records = if include_self
+ records.where(base_cte.table[:traversal_ids].lteq(namespaces[:traversal_ids]))
+ else
+ records.where(base_cte.table[:traversal_ids].lt(namespaces[:traversal_ids]))
+ end
+
+ records_cte = Gitlab::SQL::CTE.new(:descendants_cte, records)
+
+ unscoped
+ .unscope(where: [:type])
+ .with(base_cte.to_arel, records_cte.to_arel)
+ .from(records_cte.alias_to(namespaces))
end
def next_sibling_func(*args)
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
index 8d2c5d3be5a..53eac27aa54 100644
--- a/app/models/namespaces/traversal/recursive.rb
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -46,6 +46,7 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.ancestors(upto: top, hierarchy_order: hierarchy_order)
end
+ alias_method :recursive_ancestors_upto, :ancestors_upto
def self_and_ancestors(hierarchy_order: nil)
return self.class.where(id: id) unless parent_id