mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
b775f0cbdc
Most databases order tables with the `NULL` value first, having it before all other data values. Postgres has `NULLS` last. Fortunately, ANSI SQL has an option to allow the database to specify where NULLS come out in this sort order ORDER BY column ASC NULLS FIRST MS SQL, SQLite, Oracle, and Postgres all follow this syntax. Unfortunately, MySql does not. Before: PostgreSQL: both `.nulls_first()` and `.nulls_last()` work as designed. Others: both raise a runtime error. After: MySQL: `.nulls_first()` works as designed. MySQL: `.nulls_last()` raises a runtime error Others: both work as designed
110 lines
3.2 KiB
Ruby
110 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Arel # :nodoc: all
|
|
module Visitors
|
|
class PostgreSQL < Arel::Visitors::ToSql
|
|
private
|
|
def visit_Arel_Nodes_Matches(o, collector)
|
|
op = o.case_sensitive ? " LIKE " : " ILIKE "
|
|
collector = infix_value o, collector, op
|
|
if o.escape
|
|
collector << " ESCAPE "
|
|
visit o.escape, collector
|
|
else
|
|
collector
|
|
end
|
|
end
|
|
|
|
def visit_Arel_Nodes_DoesNotMatch(o, collector)
|
|
op = o.case_sensitive ? " NOT LIKE " : " NOT ILIKE "
|
|
collector = infix_value o, collector, op
|
|
if o.escape
|
|
collector << " ESCAPE "
|
|
visit o.escape, collector
|
|
else
|
|
collector
|
|
end
|
|
end
|
|
|
|
def visit_Arel_Nodes_Regexp(o, collector)
|
|
op = o.case_sensitive ? " ~ " : " ~* "
|
|
infix_value o, collector, op
|
|
end
|
|
|
|
def visit_Arel_Nodes_NotRegexp(o, collector)
|
|
op = o.case_sensitive ? " !~ " : " !~* "
|
|
infix_value o, collector, op
|
|
end
|
|
|
|
def visit_Arel_Nodes_DistinctOn(o, collector)
|
|
collector << "DISTINCT ON ( "
|
|
visit(o.expr, collector) << " )"
|
|
end
|
|
|
|
def visit_Arel_Nodes_GroupingElement(o, collector)
|
|
collector << "( "
|
|
visit(o.expr, collector) << " )"
|
|
end
|
|
|
|
def visit_Arel_Nodes_Cube(o, collector)
|
|
collector << "CUBE"
|
|
grouping_array_or_grouping_element o, collector
|
|
end
|
|
|
|
def visit_Arel_Nodes_RollUp(o, collector)
|
|
collector << "ROLLUP"
|
|
grouping_array_or_grouping_element o, collector
|
|
end
|
|
|
|
def visit_Arel_Nodes_GroupingSet(o, collector)
|
|
collector << "GROUPING SETS"
|
|
grouping_array_or_grouping_element o, collector
|
|
end
|
|
|
|
def visit_Arel_Nodes_Lateral(o, collector)
|
|
collector << "LATERAL "
|
|
grouping_parentheses o, collector
|
|
end
|
|
|
|
def visit_Arel_Nodes_IsNotDistinctFrom(o, collector)
|
|
collector = visit o.left, collector
|
|
collector << " IS NOT DISTINCT FROM "
|
|
visit o.right, collector
|
|
end
|
|
|
|
def visit_Arel_Nodes_IsDistinctFrom(o, collector)
|
|
collector = visit o.left, collector
|
|
collector << " IS DISTINCT FROM "
|
|
visit o.right, collector
|
|
end
|
|
|
|
BIND_BLOCK = proc { |i| "$#{i}" }
|
|
private_constant :BIND_BLOCK
|
|
|
|
def bind_block; BIND_BLOCK; end
|
|
|
|
# Used by Lateral visitor to enclose select queries in parentheses
|
|
def grouping_parentheses(o, collector)
|
|
if o.expr.is_a? Nodes::SelectStatement
|
|
collector << "("
|
|
visit o.expr, collector
|
|
collector << ")"
|
|
else
|
|
visit o.expr, collector
|
|
end
|
|
end
|
|
|
|
# Utilized by GroupingSet, Cube & RollUp visitors to
|
|
# handle grouping aggregation semantics
|
|
def grouping_array_or_grouping_element(o, collector)
|
|
if o.expr.is_a? Array
|
|
collector << "( "
|
|
visit o.expr, collector
|
|
collector << " )"
|
|
else
|
|
visit o.expr, collector
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|