Arel/MySQL ordering `nulls_first` and `nulls_last`

Fixes #50079 where there is unexpected behaviour for MySQL

Previously:
 - Calling nulls_first on asc worked as expected
 - Calling nulls_first on desc ordered desc nulls last
 - Calling nuls_last on asc raised error
 - Calling nulls_last on desc raised error

Now:
 - Calling nulls_first on asc works as expected
 - Calling nulls_first on desc works as expected
 - Calling nulls_last on asc works as expected
 - Calling nulls_last on desc works as expected
This commit is contained in:
tttffff 2023-11-15 21:06:25 +00:00
parent 949b4d1482
commit 059caa2065
3 changed files with 34 additions and 4 deletions

View File

@ -84,4 +84,8 @@
*Jason Meller*
* Add `nulls_last` and working `desc.nulls_first` for MySQL.
*Tristan Fellows*
Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activerecord/CHANGELOG.md) for previous changes.

View File

@ -59,9 +59,14 @@ module Arel # :nodoc: all
infix_value o, collector, " NOT REGEXP "
end
# no-op
def visit_Arel_Nodes_NullsFirst(o, collector)
visit o.expr, collector
visit(o.expr.expr, collector) << " IS NOT NULL, "
visit(o.expr, collector)
end
def visit_Arel_Nodes_NullsLast(o, collector)
visit(o.expr.expr, collector) << " IS NULL, "
visit(o.expr, collector)
end
def visit_Arel_Nodes_Cte(o, collector)

View File

@ -154,10 +154,31 @@ module Arel
end
describe "Nodes::Ordering" do
it "should no-op ascending nulls first" do
it "should handle nulls first" do
test = Table.new(:users)[:first_name].asc.nulls_first
_(compile(test)).must_be_like %{
"users"."first_name" ASC
"users"."first_name" IS NOT NULL, "users"."first_name" ASC
}
end
it "should handle nulls last" do
test = Table.new(:users)[:first_name].asc.nulls_last
_(compile(test)).must_be_like %{
"users"."first_name" IS NULL, "users"."first_name" ASC
}
end
it "should handle nulls first reversed" do
test = Table.new(:users)[:first_name].asc.nulls_first.reverse
_(compile(test)).must_be_like %{
"users"."first_name" IS NULL, "users"."first_name" DESC
}
end
it "should handle nulls last reversed" do
test = Table.new(:users)[:first_name].asc.nulls_last.reverse
_(compile(test)).must_be_like %{
"users"."first_name" IS NOT NULL, "users"."first_name" DESC
}
end
end