mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Deprecate passing ranges to #in
and #not_in
The goal of these methods should be to generate in nodes, not handle every possible permutation of more than one value. The `#between` and `#not_between` methods have been extracted, which better represent the semantics of handling ranges in SQL.
This commit is contained in:
parent
df5723dfbe
commit
f8d85cf24b
4 changed files with 202 additions and 190 deletions
|
@ -25,9 +25,23 @@ module Arel
|
|||
end
|
||||
|
||||
def between other
|
||||
left = Nodes.build_quoted(other.begin, self)
|
||||
right = Nodes.build_quoted(other.end, self)
|
||||
Nodes::Between.new(self, left.and(right))
|
||||
if other.begin == -Float::INFINITY
|
||||
if other.end == Float::INFINITY
|
||||
not_in([])
|
||||
elsif other.exclude_end?
|
||||
lt(other.end)
|
||||
else
|
||||
lteq(other.end)
|
||||
end
|
||||
elsif other.end == Float::INFINITY
|
||||
gteq(other.begin)
|
||||
elsif other.exclude_end?
|
||||
gteq(other.begin).and(lt(other.end))
|
||||
else
|
||||
left = Nodes.build_quoted(other.begin, self)
|
||||
right = Nodes.build_quoted(other.end, self)
|
||||
Nodes::Between.new(self, left.and(right))
|
||||
end
|
||||
end
|
||||
|
||||
def in other
|
||||
|
@ -35,21 +49,12 @@ module Arel
|
|||
when Arel::SelectManager
|
||||
Arel::Nodes::In.new(self, other.ast)
|
||||
when Range
|
||||
if other.begin == -Float::INFINITY
|
||||
if other.end == Float::INFINITY
|
||||
not_in([])
|
||||
elsif other.exclude_end?
|
||||
lt(other.end)
|
||||
else
|
||||
lteq(other.end)
|
||||
end
|
||||
elsif other.end == Float::INFINITY
|
||||
gteq(other.begin)
|
||||
elsif other.exclude_end?
|
||||
gteq(other.begin).and(lt(other.end))
|
||||
else
|
||||
between(other)
|
||||
if $VERBOSE
|
||||
warn <<-eowarn
|
||||
Passing a range to `#in` is deprecated. Call `#between`, instead.
|
||||
eowarn
|
||||
end
|
||||
between(other)
|
||||
when Array
|
||||
Nodes::In.new self, other.map { |x| Nodes.build_quoted(x, self) }
|
||||
else
|
||||
|
@ -65,30 +70,39 @@ module Arel
|
|||
grouping_all :in, others
|
||||
end
|
||||
|
||||
def not_between other
|
||||
if other.begin == -Float::INFINITY # The range begins with negative infinity
|
||||
if other.end == Float::INFINITY
|
||||
self.in([])
|
||||
elsif other.exclude_end?
|
||||
gteq(other.end)
|
||||
else
|
||||
gt(other.end)
|
||||
end
|
||||
elsif other.end == Float::INFINITY
|
||||
lt(other.begin)
|
||||
else
|
||||
left = lt(other.begin)
|
||||
right = if other.exclude_end?
|
||||
gteq(other.end)
|
||||
else
|
||||
gt(other.end)
|
||||
end
|
||||
left.or(right)
|
||||
end
|
||||
end
|
||||
|
||||
def not_in other
|
||||
case other
|
||||
when Arel::SelectManager
|
||||
Arel::Nodes::NotIn.new(self, other.ast)
|
||||
when Range
|
||||
if other.begin == -Float::INFINITY # The range begins with negative infinity
|
||||
if other.end == Float::INFINITY
|
||||
self.in([])
|
||||
elsif other.exclude_end?
|
||||
gteq(other.end)
|
||||
else
|
||||
gt(other.end)
|
||||
end
|
||||
elsif other.end == Float::INFINITY
|
||||
lt(other.begin)
|
||||
else
|
||||
left = lt(other.begin)
|
||||
right = if other.exclude_end?
|
||||
gteq(other.end)
|
||||
else
|
||||
gt(other.end)
|
||||
end
|
||||
left.or(right)
|
||||
if $VERBOSE
|
||||
warn <<-eowarn
|
||||
Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
||||
eowarn
|
||||
end
|
||||
not_between(other)
|
||||
when Array
|
||||
Nodes::NotIn.new self, other.map { |x| Nodes.build_quoted(x, self) }
|
||||
else
|
||||
|
|
|
@ -548,6 +548,74 @@ module Arel
|
|||
end
|
||||
end
|
||||
|
||||
describe 'with a range' do
|
||||
it 'can be constructed with a standard range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(1..3)
|
||||
|
||||
node.must_equal Nodes::Between.new(
|
||||
attribute,
|
||||
Nodes::And.new([
|
||||
Nodes::Casted.new(1, attribute),
|
||||
Nodes::Casted.new(3, attribute)
|
||||
])
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with a range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(-::Float::INFINITY..3)
|
||||
|
||||
node.must_equal Nodes::LessThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(-::Float::INFINITY...3)
|
||||
|
||||
node.must_equal Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an infinite range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(-::Float::INFINITY..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::NotIn.new(attribute, [])
|
||||
end
|
||||
|
||||
it 'can be constructed with a range ending at Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(0..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.between(0...3)
|
||||
|
||||
node.must_equal Nodes::And.new([
|
||||
Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
),
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#in' do
|
||||
it 'can be constructed with a subquery' do
|
||||
relation = Table.new(:users)
|
||||
|
@ -560,74 +628,6 @@ module Arel
|
|||
node.must_equal Nodes::In.new(attribute, mgr.ast)
|
||||
end
|
||||
|
||||
describe 'with a range' do
|
||||
it 'can be constructed with a standard range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(1..3)
|
||||
|
||||
node.must_equal Nodes::Between.new(
|
||||
attribute,
|
||||
Nodes::And.new([
|
||||
Nodes::Casted.new(1, attribute),
|
||||
Nodes::Casted.new(3, attribute)
|
||||
])
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with a range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(-::Float::INFINITY..3)
|
||||
|
||||
node.must_equal Nodes::LessThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(-::Float::INFINITY...3)
|
||||
|
||||
node.must_equal Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an infinite range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(-::Float::INFINITY..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::NotIn.new(attribute, [])
|
||||
end
|
||||
|
||||
it 'can be constructed with a range ending at Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(0..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in(0...3)
|
||||
|
||||
node.must_equal Nodes::And.new([
|
||||
Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
),
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
it 'can be constructed with a list' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.in([1, 2, 3])
|
||||
|
@ -695,6 +695,77 @@ module Arel
|
|||
end
|
||||
end
|
||||
|
||||
describe 'with a range' do
|
||||
it 'can be constructed with a standard range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(1..3)
|
||||
|
||||
node.must_equal Nodes::Grouping.new(Nodes::Or.new(
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(1, attribute)
|
||||
),
|
||||
Nodes::GreaterThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
))
|
||||
end
|
||||
|
||||
it 'can be constructed with a range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(-::Float::INFINITY..3)
|
||||
|
||||
node.must_equal Nodes::GreaterThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(-::Float::INFINITY...3)
|
||||
|
||||
node.must_equal Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an infinite range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(-::Float::INFINITY..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::In.new(attribute, [])
|
||||
end
|
||||
|
||||
it 'can be constructed with a range ending at Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(0..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_between(0...3)
|
||||
|
||||
node.must_equal Nodes::Grouping.new(Nodes::Or.new(
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
),
|
||||
Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#not_in' do
|
||||
it 'can be constructed with a subquery' do
|
||||
relation = Table.new(:users)
|
||||
|
@ -707,77 +778,6 @@ module Arel
|
|||
node.must_equal Nodes::NotIn.new(attribute, mgr.ast)
|
||||
end
|
||||
|
||||
describe 'with a range' do
|
||||
it 'can be constructed with a standard range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(1..3)
|
||||
|
||||
node.must_equal Nodes::Grouping.new(Nodes::Or.new(
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(1, attribute)
|
||||
),
|
||||
Nodes::GreaterThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
))
|
||||
end
|
||||
|
||||
it 'can be constructed with a range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(-::Float::INFINITY..3)
|
||||
|
||||
node.must_equal Nodes::GreaterThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range starting from -Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(-::Float::INFINITY...3)
|
||||
|
||||
node.must_equal Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an infinite range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(-::Float::INFINITY..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::In.new(attribute, [])
|
||||
end
|
||||
|
||||
it 'can be constructed with a range ending at Infinity' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(0..::Float::INFINITY)
|
||||
|
||||
node.must_equal Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can be constructed with an exclusive range' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in(0...3)
|
||||
|
||||
node.must_equal Nodes::Grouping.new(Nodes::Or.new(
|
||||
Nodes::LessThan.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(0, attribute)
|
||||
),
|
||||
Nodes::GreaterThanOrEqual.new(
|
||||
attribute,
|
||||
Nodes::Casted.new(3, attribute)
|
||||
)
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
it 'can be constructed with a list' do
|
||||
attribute = Attribute.new nil, nil
|
||||
node = attribute.not_in([1, 2, 3])
|
||||
|
|
|
@ -307,13 +307,11 @@ module Arel
|
|||
table = Table.new :users
|
||||
@m1 = Arel::SelectManager.new Table.engine, table
|
||||
@m1.project Arel.star
|
||||
@m1.where(table[:age].in(18..60))
|
||||
@m1.where(table[:age].between(18..60))
|
||||
|
||||
@m2 = Arel::SelectManager.new Table.engine, table
|
||||
@m2.project Arel.star
|
||||
@m2.where(table[:age].in(40..99))
|
||||
|
||||
|
||||
@m2.where(table[:age].between(40..99))
|
||||
end
|
||||
|
||||
it 'should except two managers' do
|
||||
|
|
|
@ -375,33 +375,33 @@ module Arel
|
|||
end
|
||||
|
||||
it 'can handle two dot ranges' do
|
||||
node = @attr.in 1..3
|
||||
node = @attr.between 1..3
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" BETWEEN 1 AND 3
|
||||
}
|
||||
end
|
||||
|
||||
it 'can handle three dot ranges' do
|
||||
node = @attr.in 1...3
|
||||
node = @attr.between 1...3
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" >= 1 AND "users"."id" < 3
|
||||
}
|
||||
end
|
||||
|
||||
it 'can handle ranges bounded by infinity' do
|
||||
node = @attr.in 1..Float::INFINITY
|
||||
node = @attr.between 1..Float::INFINITY
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" >= 1
|
||||
}
|
||||
node = @attr.in(-Float::INFINITY..3)
|
||||
node = @attr.between(-Float::INFINITY..3)
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" <= 3
|
||||
}
|
||||
node = @attr.in(-Float::INFINITY...3)
|
||||
node = @attr.between(-Float::INFINITY...3)
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" < 3
|
||||
}
|
||||
node = @attr.in(-Float::INFINITY..Float::INFINITY)
|
||||
node = @attr.between(-Float::INFINITY..Float::INFINITY)
|
||||
compile(node).must_be_like %{1=1}
|
||||
end
|
||||
|
||||
|
@ -479,33 +479,33 @@ module Arel
|
|||
end
|
||||
|
||||
it 'can handle two dot ranges' do
|
||||
node = @attr.not_in 1..3
|
||||
node = @attr.not_between 1..3
|
||||
compile(node).must_equal(
|
||||
%{("users"."id" < 1 OR "users"."id" > 3)}
|
||||
)
|
||||
end
|
||||
|
||||
it 'can handle three dot ranges' do
|
||||
node = @attr.not_in 1...3
|
||||
node = @attr.not_between 1...3
|
||||
compile(node).must_equal(
|
||||
%{("users"."id" < 1 OR "users"."id" >= 3)}
|
||||
)
|
||||
end
|
||||
|
||||
it 'can handle ranges bounded by infinity' do
|
||||
node = @attr.not_in 1..Float::INFINITY
|
||||
node = @attr.not_between 1..Float::INFINITY
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" < 1
|
||||
}
|
||||
node = @attr.not_in(-Float::INFINITY..3)
|
||||
node = @attr.not_between(-Float::INFINITY..3)
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" > 3
|
||||
}
|
||||
node = @attr.not_in(-Float::INFINITY...3)
|
||||
node = @attr.not_between(-Float::INFINITY...3)
|
||||
compile(node).must_be_like %{
|
||||
"users"."id" >= 3
|
||||
}
|
||||
node = @attr.not_in(-Float::INFINITY..Float::INFINITY)
|
||||
node = @attr.not_between(-Float::INFINITY..Float::INFINITY)
|
||||
compile(node).must_be_like %{1=0}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue