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-07-20 12:55:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /lib/gitlab/pagination
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'lib/gitlab/pagination')
-rw-r--r--lib/gitlab/pagination/keyset/column_order_definition.rb4
-rw-r--r--lib/gitlab/pagination/keyset/iterator.rb8
-rw-r--r--lib/gitlab/pagination/keyset/order.rb24
-rw-r--r--lib/gitlab/pagination/offset_pagination.rb15
4 files changed, 43 insertions, 8 deletions
diff --git a/lib/gitlab/pagination/keyset/column_order_definition.rb b/lib/gitlab/pagination/keyset/column_order_definition.rb
index 0c8ec02a56b..0755af9587b 100644
--- a/lib/gitlab/pagination/keyset/column_order_definition.rb
+++ b/lib/gitlab/pagination/keyset/column_order_definition.rb
@@ -120,7 +120,7 @@ module Gitlab
AREL_ORDER_CLASSES = { Arel::Nodes::Ascending => :asc, Arel::Nodes::Descending => :desc }.freeze
ALLOWED_NULLABLE_VALUES = [:not_nullable, :nulls_first, :nulls_last].freeze
- attr_reader :attribute_name, :column_expression, :order_expression, :add_to_projections
+ attr_reader :attribute_name, :column_expression, :order_expression, :add_to_projections, :order_direction
def initialize(attribute_name:, order_expression:, column_expression: nil, reversed_order_expression: nil, nullable: :not_nullable, distinct: true, order_direction: nil, add_to_projections: false)
@attribute_name = attribute_name
@@ -175,7 +175,7 @@ module Gitlab
private
- attr_reader :reversed_order_expression, :nullable, :distinct, :order_direction
+ attr_reader :reversed_order_expression, :nullable, :distinct
def calculate_reversed_order(order_expression)
unless AREL_ORDER_CLASSES.has_key?(order_expression.class) # Arel can reverse simple orders
diff --git a/lib/gitlab/pagination/keyset/iterator.rb b/lib/gitlab/pagination/keyset/iterator.rb
index 3bc8c0bf616..c6f0014a0f4 100644
--- a/lib/gitlab/pagination/keyset/iterator.rb
+++ b/lib/gitlab/pagination/keyset/iterator.rb
@@ -4,8 +4,12 @@ module Gitlab
module Pagination
module Keyset
class Iterator
- def initialize(scope:, use_union_optimization: false)
- @scope = scope
+ UnsupportedScopeOrder = Class.new(StandardError)
+
+ def initialize(scope:, use_union_optimization: true)
+ @scope, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(scope)
+ raise(UnsupportedScopeOrder, 'The order on the scope does not support keyset pagination') unless success
+
@order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope)
@use_union_optimization = use_union_optimization
end
diff --git a/lib/gitlab/pagination/keyset/order.rb b/lib/gitlab/pagination/keyset/order.rb
index cef3a7b291a..19d44ee69dd 100644
--- a/lib/gitlab/pagination/keyset/order.rb
+++ b/lib/gitlab/pagination/keyset/order.rb
@@ -139,6 +139,8 @@ module Gitlab
verify_incoming_values!(values)
+ return use_composite_row_comparison(values) if composite_row_comparison_possible?
+
where_values = []
reversed_column_definitions = column_definitions.reverse
@@ -187,6 +189,28 @@ module Gitlab
private
+ def composite_row_comparison_possible?
+ !column_definitions.one? &&
+ column_definitions.all?(&:not_nullable?) &&
+ column_definitions.map(&:order_direction).uniq.one? # all columns uses the same order direction
+ end
+
+ # composite row comparison works with NOT NULL columns and may use only one index scan given a proper index setup
+ # Example: (created_at, id) > ('2012-09-18 01:40:01+00', 15)
+ def use_composite_row_comparison(values)
+ columns = Arel::Nodes::Grouping.new(column_definitions.map(&:column_expression))
+ values = Arel::Nodes::Grouping.new(column_definitions.map do |column_definition|
+ value = values[column_definition.attribute_name]
+ Arel::Nodes.build_quoted(value, column_definition.column_expression)
+ end)
+
+ if column_definitions.first.ascending_order?
+ [columns.gt(values)]
+ else
+ [columns.lt(values)]
+ end
+ end
+
# Adds extra columns to the SELECT clause
def apply_custom_projections(scope)
additional_projections = column_definitions.select(&:add_to_projections).map do |column_definition|
diff --git a/lib/gitlab/pagination/offset_pagination.rb b/lib/gitlab/pagination/offset_pagination.rb
index 2805b12d95d..4f8a6ffb2cc 100644
--- a/lib/gitlab/pagination/offset_pagination.rb
+++ b/lib/gitlab/pagination/offset_pagination.rb
@@ -19,11 +19,10 @@ module Gitlab
private
def paginate_with_limit_optimization(relation)
- # do not paginate relation if it is already paginated
- pagination_data = if relation.respond_to?(:current_page) && relation.current_page == params[:page] && relation.limit_value == params[:per_page]
- relation
- else
+ pagination_data = if needs_pagination?(relation)
relation.page(params[:page]).per(params[:per_page])
+ else
+ relation
end
return pagination_data unless pagination_data.is_a?(ActiveRecord::Relation)
@@ -39,6 +38,14 @@ module Gitlab
end
end
+ def needs_pagination?(relation)
+ return true unless relation.respond_to?(:current_page)
+ return true if params[:page].present? && relation.current_page != params[:page].to_i
+ return true if params[:per_page].present? && relation.limit_value != params[:per_page].to_i
+
+ false
+ end
+
def add_default_order(relation)
if relation.is_a?(ActiveRecord::Relation) && relation.order_values.empty?
relation = relation.order(:id) # rubocop: disable CodeReuse/ActiveRecord