mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #23523 from kamipo/avoid_truncation_in_uniqueness_validation
Avoid a string value truncation in uniqueness validation
This commit is contained in:
commit
f2f2d64429
3 changed files with 49 additions and 13 deletions
|
@ -1,3 +1,20 @@
|
|||
* SQLite: Fix uniqueness validation when values exceed the column limit.
|
||||
|
||||
SQLite doesn't impose length restrictions on strings, BLOBs, or numeric
|
||||
values. It treats them as helpful metadata. When we truncate strings
|
||||
before checking uniqueness, we'd miss values that exceed the column limit.
|
||||
|
||||
Other databases enforce length limits. A large value will pass uniqueness
|
||||
validation since the column limit guarantees no value that long exists.
|
||||
When we insert the row, it'll raise `ActiveRecord::ValueTooLong` as we
|
||||
expect.
|
||||
|
||||
This fixes edge-case incorrect validation failures for values that exceed
|
||||
the column limit but are identical to an existing value *when truncated*.
|
||||
Now these will pass validation and raise an exception.
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Raise `ActiveRecord::ValueTooLong` when column limits are exceeded.
|
||||
Supported by MySQL and PostgreSQL adapters.
|
||||
|
||||
|
|
|
@ -67,9 +67,6 @@ module ActiveRecord
|
|||
cast_type = klass.type_for_attribute(attribute_name)
|
||||
value = cast_type.serialize(value)
|
||||
value = klass.connection.type_cast(value)
|
||||
if value.is_a?(String) && column.limit
|
||||
value = value.to_s[0, column.limit]
|
||||
end
|
||||
|
||||
comparison = if !options[:case_sensitive] && !value.nil?
|
||||
# will use SQL LOWER function before comparison, unless it detects a case insensitive collation
|
||||
|
|
|
@ -349,19 +349,41 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
def test_validate_uniqueness_with_limit
|
||||
# Event.title is limited to 5 characters
|
||||
e1 = Event.create(:title => "abcde")
|
||||
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
||||
e2 = Event.create(:title => "abcdefgh")
|
||||
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
||||
if current_adapter?(:SQLite3Adapter)
|
||||
# Event.title has limit 5, but SQLite doesn't truncate.
|
||||
e1 = Event.create(title: "abcdefgh")
|
||||
assert e1.valid?, "Could not create an event with a unique 8 characters title"
|
||||
|
||||
e2 = Event.create(title: "abcdefgh")
|
||||
assert_not e2.valid?, "Created an event whose title is not unique"
|
||||
elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :SQLServerAdapter)
|
||||
assert_raise(ActiveRecord::ValueTooLong) do
|
||||
Event.create(title: "abcdefgh")
|
||||
end
|
||||
else
|
||||
assert_raise(ActiveRecord::StatementInvalid) do
|
||||
Event.create(title: "abcdefgh")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_uniqueness_with_limit_and_utf8
|
||||
# Event.title is limited to 5 characters
|
||||
e1 = Event.create(:title => "一二三四五")
|
||||
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
||||
e2 = Event.create(:title => "一二三四五六七八")
|
||||
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
||||
if current_adapter?(:SQLite3Adapter)
|
||||
# Event.title has limit 5, but does SQLite doesn't truncate.
|
||||
e1 = Event.create(title: "一二三四五六七八")
|
||||
assert e1.valid?, "Could not create an event with a unique 8 characters title"
|
||||
|
||||
e2 = Event.create(title: "一二三四五六七八")
|
||||
assert_not e2.valid?, "Created an event whose title is not unique"
|
||||
elsif current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter, :SQLServerAdapter)
|
||||
assert_raise(ActiveRecord::ValueTooLong) do
|
||||
Event.create(title: "一二三四五六七八")
|
||||
end
|
||||
else
|
||||
assert_raise(ActiveRecord::StatementInvalid) do
|
||||
Event.create(title: "一二三四五六七八")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_straight_inheritance_uniqueness
|
||||
|
|
Loading…
Reference in a new issue