class OrderQuery::SQL::OrderBy

Constructs SQL for ORDER BY.

Constants

ENUM_SET_TRUE_FALSE_NIL

Public Class Methods

new(columns) click to toggle source

@param [Array<Column>]

# File lib/order_query/sql/order_by.rb, line 8
def initialize(columns)
  @columns = columns
end

Public Instance Methods

build() click to toggle source

@return [String]

# File lib/order_query/sql/order_by.rb, line 13
def build
  @sql ||= join_order_by_clauses order_by_sql_clauses
end
build_reverse() click to toggle source

@return [String]

# File lib/order_query/sql/order_by.rb, line 18
def build_reverse
  @reverse_sql ||= join_order_by_clauses order_by_sql_clauses(true)
end

Protected Instance Methods

column_clause(col, reverse = false) click to toggle source
# File lib/order_query/sql/order_by.rb, line 29
def column_clause(col, reverse = false)
  if col.order_enum
    column_clause_enum col, reverse
  else
    column_clause_ray col, reverse
  end
end
column_clause_enum(col, reverse = false) click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/order_query/sql/order_by.rb, line 48
def column_clause_enum(col, reverse = false)
  # Collapse booleans enum to `ORDER BY column ASC|DESC`
  return optimize_enum_bools(col, reverse) if optimize_enum_bools?(col)
  if optimize_enum_bools_nil?(col)
    return optimize_enum_bools_nil(col, reverse)
  end

  clauses = []
  with_nulls = false
  if col.order_enum.include?(nil)
    with_nulls = true
  elsif needs_null_sort?(col, reverse)
    clauses << order_by_nulls_sql(col, reverse)
  end
  clauses.concat(col.order_enum.map do |v|
    "#{order_by_value_sql col, v, with_nulls} " \
      "#{sort_direction_sql(col, reverse)}"
  end)
  clauses.join(', ').freeze
end
column_clause_ray(col, reverse = false, with_null_clause = needs_null_sort?(col, reverse)) click to toggle source
# File lib/order_query/sql/order_by.rb, line 37
def column_clause_ray(col, reverse = false,
                      with_null_clause = needs_null_sort?(col, reverse))
  clauses = []
  # TODO: use NULLS FIRST/LAST where supported.
  clauses << order_by_nulls_sql(col, reverse) if with_null_clause
  clauses << "#{col.column_name} #{sort_direction_sql(col, reverse)}"
  clauses.join(', ').freeze
end
join_order_by_clauses(clauses) click to toggle source

@param [Array<String>] clauses

# File lib/order_query/sql/order_by.rb, line 104
def join_order_by_clauses(clauses)
  clauses.join(', ').freeze
end
needs_null_sort?(col, reverse, nulls_direction = col.nulls_direction(reverse)) click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/order_query/sql/order_by.rb, line 70
def needs_null_sort?(col, reverse,
                     nulls_direction = col.nulls_direction(reverse))
  return false unless col.nullable?

  nulls_direction != col.default_nulls_direction(reverse)
end
order_by_nulls_sql(col, reverse) click to toggle source
# File lib/order_query/sql/order_by.rb, line 77
def order_by_nulls_sql(col, reverse)
  if col.default_nulls_direction !=
     (col.direction == :asc ? :first : :last)
    reverse = !reverse
  end
  "#{col.column_name} IS NULL #{sort_direction_sql(col, reverse)}"
end
order_by_sql_clauses(reverse = false) click to toggle source

@return [Array<String>]

# File lib/order_query/sql/order_by.rb, line 25
def order_by_sql_clauses(reverse = false)
  @columns.map { |col| column_clause col, reverse }
end
order_by_value_sql(col, v, with_nulls = false) click to toggle source
# File lib/order_query/sql/order_by.rb, line 85
def order_by_value_sql(col, v, with_nulls = false)
  if with_nulls
    if v.nil?
      "#{col.column_name} IS NULL"
    else
      "#{col.column_name} IS NOT NULL AND " \
         "#{col.column_name}=#{col.quote v}"
    end
  else
    "#{col.column_name}=#{col.quote v}"
  end
end
sort_direction_sql(col, reverse = false) click to toggle source

@return [String]

# File lib/order_query/sql/order_by.rb, line 99
def sort_direction_sql(col, reverse = false)
  col.direction(reverse).to_s.upcase.freeze
end

Private Instance Methods

optimize_enum_bools(col, reverse) click to toggle source
# File lib/order_query/sql/order_by.rb, line 114
def optimize_enum_bools(col, reverse)
  column_clause_ray(col, col.order_enum[-1] ^ reverse)
end
optimize_enum_bools?(col) click to toggle source
# File lib/order_query/sql/order_by.rb, line 110
def optimize_enum_bools?(col)
  col.order_enum == [false, true] || col.order_enum == [true, false]
end
optimize_enum_bools_nil(col, reverse) click to toggle source
# File lib/order_query/sql/order_by.rb, line 125
def optimize_enum_bools_nil(col, reverse)
  last_bool_true = if col.order_enum[-1].nil?
                     col.order_enum[-2]
                   else
                     col.order_enum[-1]
                   end
  reverse_override = last_bool_true ^ reverse
  with_nulls_sort =
    needs_null_sort?(col, reverse_override, col.nulls_direction(reverse))
  column_clause_ray(col, reverse_override, with_nulls_sort)
end
optimize_enum_bools_nil?(col) click to toggle source
# File lib/order_query/sql/order_by.rb, line 120
def optimize_enum_bools_nil?(col)
  Set.new(col.order_enum) == ENUM_SET_TRUE_FALSE_NIL &&
    !col.order_enum[1].nil?
end