module Sequel::SeekPagination

Constants

VERSION

Public Instance Methods

get_order_values_for_pk(pk, raise_on_failure: false) click to toggle source
# File lib/sequel/extensions/seek_pagination.rb, line 73
def get_order_values_for_pk(pk, raise_on_failure: false)
  order = opts[:order]

  unless model = opts[:model]
    raise Error, "attempted a primary key lookup on a dataset that doesn't have an associated model"
  end

  al = nil
  aliases = order.map { al = al ? al.next : :a }

  ds =
    cached_dataset(:_seek_pagination_get_order_values_ds) do
      # Need to load the values to order from for that pk from the DB, so we
      # need to fetch the actual expressions being ordered by. Also,
      # Dataset#get won't like it if we pass it expressions that aren't
      # simple columns, so we need to give it aliases for everything.
      naked.limit(1).select(
        *order.map.with_index { |o, i|
          expression = Sequel::SQL::OrderedExpression === o ? o.expression : o
          Sequel.as(expression, aliases[i])
        }
      )
    end

  condition = model.qualified_primary_key_hash(pk)

  if result = ds.where_all(condition).first
    result.values_at(*aliases)
  elsif raise_on_failure
    raise NoMatchingRow.new(ds.where(condition))
  end
end
seek(missing_pk: :raise, **args) click to toggle source
# File lib/sequel/extensions/seek_pagination.rb, line 8
def seek(missing_pk: :raise, **args)
  if c = seek_conditions(raise_on_missing_pk: missing_pk == :raise, **args)
    where(c)
  else
    case missing_pk
    when :ignore     then self
    when :nullify    then nullify
    when :return_nil then nil
    else raise Error, "passed an invalid argument for missing_pk: #{missing_pk.inspect}"
    end
  end
end
seek_conditions( value: nil, pk: nil, include_exact_match: false, not_null: nil, raise_on_missing_pk: false ) click to toggle source
# File lib/sequel/extensions/seek_pagination.rb, line 21
def seek_conditions(
  value: nil,
  pk: nil,
  include_exact_match: false,
  not_null: nil,
  raise_on_missing_pk: false
)

  order = opts[:order]
  model = opts[:model]

  if !(value.nil? ^ pk.nil?)
    raise Error, "must pass exactly one of :value and :pk to #seek"
  elsif order.nil? || order.length.zero?
    raise Error, "cannot call #seek on a dataset with no order"
  end

  values =
    if pk
      get_order_values_for_pk(pk, raise_on_failure: raise_on_missing_pk)
    else
      Array(value)
    end

  return unless values

  if values.length != order.length
    raise Error, "passed the wrong number of values to #seek"
  end

  if not_null.nil?
    not_null = []

    # If the dataset was chained off a model, use its stored schema
    # information to figure out what columns are not null.
    if model
      table = model.table_name

      model.db_schema.each do |column, schema|
        next if schema[:allow_null]
        not_null << column << Sequel.qualify(table, column)
      end
    end
  end

  OrderedColumnSet.new(
    order.zip(values),
    include_exact_match: include_exact_match,
    not_null: not_null
  ).build_conditions
end