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