Class: Gitlab::Graphql::Pagination::Keyset::QueryBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/graphql/pagination/keyset/query_builder.rb

Instance Method Summary collapse

Constructor Details

#initialize(arel_table, order_list, decoded_cursor, before_or_after) ⇒ QueryBuilder

Returns a new instance of QueryBuilder.


8
9
10
11
12
13
14
# File 'lib/gitlab/graphql/pagination/keyset/query_builder.rb', line 8

def initialize(arel_table, order_list, decoded_cursor, before_or_after)
  @arel_table, @order_list, @decoded_cursor, @before_or_after = arel_table, order_list, decoded_cursor, before_or_after

  if order_list.empty?
    raise ArgumentError.new('No ordering scopes have been supplied')
  end
end

Instance Method Details

#conditionsObject

Based on whether the main field we're ordering on is NULL in the cursor, we can more easily target our query condition. We assume that the last ordering field is unique, meaning it will not contain NULLs. We currently only support two ordering fields.

Example of the conditions for

relation: Issue.order(relative_position: :asc).order(id: :asc)
after cursor: relative_position: 1500, id: 500

when cursor[relative_position] is not NULL

    ("issues"."relative_position" > 1500)
    OR (
      "issues"."relative_position" = 1500
      AND
      "issues"."id" > 500
    )
    OR ("issues"."relative_position" IS NULL)

when cursor[relative_position] is NULL

    "issues"."relative_position" IS NULL
    AND
    "issues"."id" > 500

42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/gitlab/graphql/pagination/keyset/query_builder.rb', line 42

def conditions
  attr_values = order_list.map { |field| decoded_cursor[field.attribute_name] }

  if order_list.count == 1 && attr_values.first.nil?
    raise Gitlab::Graphql::Errors::ArgumentError.new('Before/after cursor invalid: `nil` was provided as only sortable value')
  end

  if order_list.count == 1 || attr_values.first.present?
    Keyset::Conditions::NotNullCondition.new(arel_table, order_list, attr_values, operators, before_or_after).build
  else
    Keyset::Conditions::NullCondition.new(arel_table, order_list, attr_values, operators, before_or_after).build
  end
end