Module: Card::Query::CardQuery::Sorting

Included in:
Card::Query::CardQuery
Defined in:
lib/card/query/card_query/sorting.rb

Overview

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.)

Constant Summary collapse

SORT_BY_ITEM_JOIN_MAP =
{ left: "left_id", right: "right_id" }.freeze

Instance Method Summary collapse

Instance Method Details

#count_sort_queryObject



82
83
84
85
86
# 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) ⇒ Object



78
79
80
# 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 = {}) ⇒ Object



88
89
90
91
92
93
94
95
96
97
# 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) ⇒ Object



69
70
71
72
73
74
75
76
# 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) ⇒ Object



17
18
19
20
21
22
23
# 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) ⇒ Object



25
26
27
28
29
30
31
# 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) ⇒ Object

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



48
49
50
51
52
# 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) ⇒ Object



58
59
60
61
62
63
64
65
66
67
# 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) ⇒ Object



33
34
35
36
37
38
39
# 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) ⇒ Object



41
42
43
# 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) ⇒ Object



54
55
56
# 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