Pārlūkot izejas kodu

Fixed #32793 -- Fixed loss of precision for temporal operations with DecimalFields on MySQL.

Regression in 1e38f1191de21b6e96736f58df57dfb851a28c1f.

Thanks Mohsen Tamiz for the report.
Mariusz Felisiak 3 gadi atpakaļ
vecāks
revīzija
e703b152c6

+ 3 - 0
django/db/backends/mysql/operations.py

@@ -160,6 +160,9 @@ class DatabaseOperations(BaseDatabaseOperations):
         """
         return [(None, ("NULL", [], False))]
 
+    def adapt_decimalfield_value(self, value, max_digits=None, decimal_places=None):
+        return value
+
     def last_executed_query(self, cursor, sql, params):
         # With MySQLdb, cursor objects have an (undocumented) "_executed"
         # attribute where the exact query sent to the database is saved.

+ 3 - 0
docs/releases/3.2.4.txt

@@ -28,3 +28,6 @@ Bugfixes
 
 * Fixed a regression in Django 3.2 that caused a crash of auto-reloader with
   ``AttributeError``, e.g. inside a ``Conda`` environment (:ticket:`32783`).
+
+* Fixed a regression in Django 3.2 that caused a loss of precision for
+  operations with ``DecimalField`` on MySQL (:ticket:`32793`).

+ 2 - 1
tests/expressions/models.py

@@ -48,9 +48,10 @@ class Company(models.Model):
 class Number(models.Model):
     integer = models.BigIntegerField(db_column='the_integer')
     float = models.FloatField(null=True, db_column='the_float')
+    decimal_value = models.DecimalField(max_digits=20, decimal_places=17, null=True)
 
     def __str__(self):
-        return '%i, %.3f' % (self.integer, self.float)
+        return '%i, %.3f, %.17f' % (self.integer, self.float, self.decimal_value)
 
 
 class Experiment(models.Model):

+ 7 - 0
tests/expressions/tests.py

@@ -1194,6 +1194,13 @@ class ExpressionsNumericTests(TestCase):
         self.assertEqual(Number.objects.get(pk=n.pk).integer, 10)
         self.assertEqual(Number.objects.get(pk=n.pk).float, Approximate(256.900, places=3))
 
+    def test_decimal_expression(self):
+        n = Number.objects.create(integer=1, decimal_value=Decimal('0.5'))
+        n.decimal_value = F('decimal_value') - Decimal('0.4')
+        n.save()
+        n.refresh_from_db()
+        self.assertEqual(n.decimal_value, Decimal('0.1'))
+
 
 class ExpressionOperatorTests(TestCase):
     @classmethod