aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/predicate_builder
diff options
context:
space:
mode:
authorSean Griffin <sean@seantheprogrammer.com>2016-01-21 13:25:45 -0700
committerSean Griffin <sean@seantheprogrammer.com>2016-01-21 13:27:40 -0700
commit6efb39456a8ee3569f3787cc2f26c041365a0e27 (patch)
tree64baefcb441405b19148974d78ec4bc3739dee8a /activerecord/lib/active_record/relation/predicate_builder
parent71d6826d2989ae0cf1d44f10ea73d4f9dd5f7cc6 (diff)
downloadrails-6efb39456a8ee3569f3787cc2f26c041365a0e27.tar.gz
rails-6efb39456a8ee3569f3787cc2f26c041365a0e27.tar.bz2
rails-6efb39456a8ee3569f3787cc2f26c041365a0e27.zip
Use bind parameters for ranges in where clauses
This is a similar case to wanting ot use bind params for limit and offset. Right now passing a range grows the amount of prepared statements in an unbounded fashion. We could avoid using prepared statements in that case, similar to what we do with arrays, but there's a known number of variants for ranges. This ends up duplicating some of the logic from Arel for how to handle potentially infinite ranges, and that behavior may be removed from Arel in the future. Fixes #23074
Diffstat (limited to 'activerecord/lib/active_record/relation/predicate_builder')
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/range_handler.rb18
1 files changed, 17 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder/range_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/range_handler.rb
index 1b3849e3ad..306d4694ae 100644
--- a/activerecord/lib/active_record/relation/predicate_builder/range_handler.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder/range_handler.rb
@@ -1,12 +1,28 @@
module ActiveRecord
class PredicateBuilder
class RangeHandler # :nodoc:
+ RangeWithBinds = Struct.new(:begin, :end, :exclude_end?)
+
def initialize(predicate_builder)
@predicate_builder = predicate_builder
end
def call(attribute, value)
- attribute.between(value)
+ if value.begin.respond_to?(:infinite?) && value.begin.infinite?
+ if value.end.respond_to?(:infinite?) && value.end.infinite?
+ attribute.not_in([])
+ elsif value.exclude_end?
+ attribute.lt(value.end)
+ else
+ attribute.lteq(value.end)
+ end
+ elsif value.end.respond_to?(:infinite?) && value.end.infinite?
+ attribute.gteq(value.begin)
+ elsif value.exclude_end?
+ attribute.gteq(value.begin).and(attribute.lt(value.end))
+ else
+ attribute.between(value)
+ end
end
protected