[1.8.x] Fixed #25767 -- Fixed data truncation possibility with Positive(Small)IntegerField on MySQL.
Backport of 710e11d076
from master
This commit is contained in:
parent
acaf30ad17
commit
581b9e5047
|
@ -13,8 +13,8 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||||
|
|
||||||
# MySQL stores positive fields as UNSIGNED ints.
|
# MySQL stores positive fields as UNSIGNED ints.
|
||||||
integer_field_ranges = dict(BaseDatabaseOperations.integer_field_ranges,
|
integer_field_ranges = dict(BaseDatabaseOperations.integer_field_ranges,
|
||||||
PositiveSmallIntegerField=(0, 4294967295),
|
PositiveSmallIntegerField=(0, 65535),
|
||||||
PositiveIntegerField=(0, 18446744073709551615),
|
PositiveIntegerField=(0, 4294967295),
|
||||||
)
|
)
|
||||||
|
|
||||||
def date_extract_sql(self, lookup_type, field_name):
|
def date_extract_sql(self, lookup_type, field_name):
|
||||||
|
|
|
@ -46,3 +46,8 @@ Bugfixes
|
||||||
* Fixed ``set_FOO_order()`` crash when the ``ForeignKey`` of a model with
|
* Fixed ``set_FOO_order()`` crash when the ``ForeignKey`` of a model with
|
||||||
``order_with_respect_to`` references a model with a ``OneToOneField``
|
``order_with_respect_to`` references a model with a ``OneToOneField``
|
||||||
primary key (:ticket:`25786`).
|
primary key (:ticket:`25786`).
|
||||||
|
|
||||||
|
* Fixed incorrect validation for ``PositiveIntegerField`` and
|
||||||
|
``PositiveSmallIntegerField`` on MySQL resulting in values greater than
|
||||||
|
4294967295 or 65535, respectively, passing validation and being silently
|
||||||
|
truncated by the database (:ticket:`25767`).
|
||||||
|
|
|
@ -506,6 +506,12 @@ class IntegerFieldTests(test.TestCase):
|
||||||
model = IntegerModel
|
model = IntegerModel
|
||||||
documented_range = (-2147483648, 2147483647)
|
documented_range = (-2147483648, 2147483647)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def backend_range(self):
|
||||||
|
field = self.model._meta.get_field('value')
|
||||||
|
internal_type = field.get_internal_type()
|
||||||
|
return connection.ops.integer_field_range(internal_type)
|
||||||
|
|
||||||
def test_documented_range(self):
|
def test_documented_range(self):
|
||||||
"""
|
"""
|
||||||
Ensure that values within the documented safe range pass validation,
|
Ensure that values within the documented safe range pass validation,
|
||||||
|
@ -527,14 +533,34 @@ class IntegerFieldTests(test.TestCase):
|
||||||
self.assertEqual(qs.count(), 1)
|
self.assertEqual(qs.count(), 1)
|
||||||
self.assertEqual(qs[0].value, max_value)
|
self.assertEqual(qs[0].value, max_value)
|
||||||
|
|
||||||
|
def test_backend_range_save(self):
|
||||||
|
"""
|
||||||
|
Ensure that backend specific range can be saved without corruption.
|
||||||
|
"""
|
||||||
|
min_value, max_value = self.backend_range
|
||||||
|
|
||||||
|
if min_value is not None:
|
||||||
|
instance = self.model(value=min_value)
|
||||||
|
instance.full_clean()
|
||||||
|
instance.save()
|
||||||
|
qs = self.model.objects.filter(value__lte=min_value)
|
||||||
|
self.assertEqual(qs.count(), 1)
|
||||||
|
self.assertEqual(qs[0].value, min_value)
|
||||||
|
|
||||||
|
if max_value is not None:
|
||||||
|
instance = self.model(value=max_value)
|
||||||
|
instance.full_clean()
|
||||||
|
instance.save()
|
||||||
|
qs = self.model.objects.filter(value__gte=max_value)
|
||||||
|
self.assertEqual(qs.count(), 1)
|
||||||
|
self.assertEqual(qs[0].value, max_value)
|
||||||
|
|
||||||
def test_backend_range_validation(self):
|
def test_backend_range_validation(self):
|
||||||
"""
|
"""
|
||||||
Ensure that backend specific range are enforced at the model
|
Ensure that backend specific range are enforced at the model
|
||||||
validation level. ref #12030.
|
validation level. ref #12030.
|
||||||
"""
|
"""
|
||||||
field = self.model._meta.get_field('value')
|
min_value, max_value = self.backend_range
|
||||||
internal_type = field.get_internal_type()
|
|
||||||
min_value, max_value = connection.ops.integer_field_range(internal_type)
|
|
||||||
|
|
||||||
if min_value is not None:
|
if min_value is not None:
|
||||||
instance = self.model(value=min_value - 1)
|
instance = self.model(value=min_value - 1)
|
||||||
|
|
Loading…
Reference in New Issue