1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Prevent making bind param if casted value is nil

If casted value is nil, generated SQL should be `IS NULL`. But currently
it is generated as `= NULL`. To prevent this behavior, avoid making bind
param if casted value is nil.

Fixes #28945.
This commit is contained in:
Ryuta Kamizono 2017-05-11 04:20:53 +09:00
parent 7c800fe5e3
commit 67a4a9feb9
5 changed files with 24 additions and 9 deletions

View file

@ -1,3 +1,7 @@
* Prevent making bind param if casted value is nil.
*Ryuta Kamizono*
* Deprecate passing arguments and block at the same time to `count` and `sum` in `ActiveRecord::Calculations`.
*Ryuta Kamizono*

View file

@ -107,21 +107,26 @@ module ActiveRecord
first = value.begin
last = value.end
unless first.respond_to?(:infinite?) && first.infinite?
binds << build_bind_param(column_name, first)
binds << build_bind_attribute(column_name, first)
first = Arel::Nodes::BindParam.new
end
unless last.respond_to?(:infinite?) && last.infinite?
binds << build_bind_param(column_name, last)
binds << build_bind_attribute(column_name, last)
last = Arel::Nodes::BindParam.new
end
result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
when value.is_a?(Relation)
binds.concat(value.bound_attributes)
else
if can_be_bound?(column_name, value)
result[column_name] = Arel::Nodes::BindParam.new
binds << build_bind_param(column_name, value)
elsif value.is_a?(Relation)
binds.concat(value.bound_attributes)
bind_attribute = build_bind_attribute(column_name, value)
if value.is_a?(StatementCache::Substitute) || !bind_attribute.value_for_database.nil?
result[column_name] = Arel::Nodes::BindParam.new
binds << bind_attribute
else
result[column_name] = nil
end
end
end
end
@ -164,7 +169,7 @@ module ActiveRecord
end
end
def build_bind_param(column_name, value)
def build_bind_attribute(column_name, value)
Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
end
end

View file

@ -57,7 +57,7 @@ module ActiveRecord
else
column = klass.column_for_attribute(attribute)
binds << predicate_builder.send(:build_bind_param, attribute, value)
binds << predicate_builder.send(:build_bind_attribute, attribute, value)
value = Arel::Nodes::BindParam.new
predicate = if options[:case_sensitive]

View file

@ -60,6 +60,7 @@ class EnumTest < ActiveRecord::TestCase
assert_not_equal @book, Book.where(status: [:written]).first
assert_not_equal @book, Book.where.not(status: :published).first
assert_equal @book, Book.where.not(status: :written).first
assert_equal books(:ddd), Book.where(read_status: :forgotten).first
end
test "find via where with strings" do
@ -69,6 +70,7 @@ class EnumTest < ActiveRecord::TestCase
assert_not_equal @book, Book.where(status: ["written"]).first
assert_not_equal @book, Book.where.not(status: "published").first
assert_equal @book, Book.where.not(status: "written").first
assert_equal books(:ddd), Book.where(read_status: "forgotten").first
end
test "build from scope" do

View file

@ -15,7 +15,7 @@ require "models/vertex"
module ActiveRecord
class WhereTest < ActiveRecord::TestCase
fixtures :posts, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates
fixtures :posts, :edges, :authors, :author_addresses, :binaries, :essays, :cars, :treasures, :price_estimates, :topics
def test_where_copies_bind_params
author = authors(:david)
@ -48,6 +48,10 @@ module ActiveRecord
assert_equal [chef], chefs.to_a
end
def test_where_with_casted_value_is_nil
assert_equal 4, Topic.where(last_read: "").count
end
def test_rewhere_on_root
assert_equal posts(:welcome), Post.rewhere(title: "Welcome to the weblog").first
end