module Card::Query::CardQuery::Sorting

handle relational (not simple) CQL sort values (see interpret_as_modifier? and order_directives)

sorting with subqueries is not fully supported; only a few experimental examples have been attempted, and even for those the syntax is likely to change.

Generally speaking, sorting subqueries will require a JOIN strategy (as opposed to the “WHERE EXISTS” strategy that is central to queries’ main conditions.)

Constants

SORT_BY_ITEM_JOIN_MAP

Public Instance Methods

count_sort_query() click to toggle source
# File lib/card/query/card_query/sorting.rb, line 82
def count_sort_query
  Query.new return: "coalesce(count(*), 0) as count",
            group: "sort_join_field",
            superquery: self
end
count_subselect(val) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 78
def count_subselect val
  Query.new val.merge(return: "id", superquery: self)
end
join_cards(val, opts={}) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 88
def join_cards val, opts={}
  conditions_on_join = opts.delete :conditions_on_join
  s = subquery
  join_opts = { from: self, to: s }.merge opts
  card_join = Join.new join_opts
  joins << card_join unless opts[:from].is_a? Join
  s.conditions_on_join = card_join if conditions_on_join
  s.interpret val
  s
end
join_count_sort_query(sort_query) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 69
def join_count_sort_query sort_query
  sort_query.mods[:sort_join_field] =
    "#{sort_query.table_alias}.id as sort_join_field"
  # FIXME: HACK!

  joins << Join.new(from: self, side: "LEFT",
                    to: [sort_query, "srtbl", "sort_join_field"])
end
sort(val) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 17
def sort val
  return nil unless full? # eg, no sorting on simple count queries

  interpret_sort_hash val do |value, item, sort_field|
    sort_by value, item, sort_field
  end
end
sort_by(val, item, sort_field) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 25
def sort_by val, item, sort_field
  if sort_field == "count"
    sort_by_count val, item
  else
    sort_by_item_join val, item, sort_field
  end
end
sort_by_count(val, item) click to toggle source

EXPERIMENTAL! sort_by: { referred_to_by { right: “*follow” }, return count }

# File lib/card/query/card_query/sorting.rb, line 48
def sort_by_count val, item
  method_name = "sort_by_count_#{item}"
  sort_method_not_implemented :count, item unless respond_to? method_name
  send method_name, val
end
sort_by_count_referred_to(val) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 58
def sort_by_count_referred_to val
  @mods[:sort_by] = "coalesce(count,0)" # needed for postgres
  sort_query = count_sort_query
  sort_query.add_condition "referer_id in (#{count_subselect(val).sql})"
  # FIXME: - SQL generated before SQL phase

  sort_query.joins << Join.new(from: sort_query, side: "LEFT",
                               to: %w[card_references wr referee_id])
  join_count_sort_query sort_query
end
sort_by_item_join(val, item, sort_field) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 33
def sort_by_item_join val, item, sort_field
  join_field = sort_by_item_join_field item
  join = join_cards val, to_field: join_field,
                         side: "LEFT",
                         conditions_on_join: true
  @mods[:sort_by] ||= "#{join.table_alias}.#{sort_field}"
end
sort_by_item_join_field(item) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 41
def sort_by_item_join_field item
  SORT_BY_ITEM_JOIN_MAP[item.to_sym] || sort_method_not_implemented(:join, item)
end
sort_method_not_implemented(method, item) click to toggle source
# File lib/card/query/card_query/sorting.rb, line 54
def sort_method_not_implemented method, item
  raise Card::Error::BadQuery, "sorting by ##{method}/#{item} not yet implemented"
end

Private Instance Methods

interpret_sort_hash(val) { |val, item, sort_field| ... } click to toggle source
# File lib/card/query/card_query/sorting.rb, line 101
def interpret_sort_hash val
  val = val.symbolize_keys
  item = val.delete(:item) || "left"
  sort_field = val[:return] || "db_content"
  yield val, item, sort_field
end