From e703b152c6148ddda1b072a4353e9a41dca87f90 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Tue, 1 Jun 2021 15:11:42 +0200 Subject: [PATCH] Fixed #32793 -- Fixed loss of precision for temporal operations with DecimalFields on MySQL. Regression in 1e38f1191de21b6e96736f58df57dfb851a28c1f. Thanks Mohsen Tamiz for the report. --- django/db/backends/mysql/operations.py | 3 +++ docs/releases/3.2.4.txt | 3 +++ tests/expressions/models.py | 3 ++- tests/expressions/tests.py | 7 +++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py index 4faa7db617..89730cee29 100644 --- a/django/db/backends/mysql/operations.py +++ b/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. diff --git a/docs/releases/3.2.4.txt b/docs/releases/3.2.4.txt index 9941bd7513..b6f7593f2d 100644 --- a/docs/releases/3.2.4.txt +++ b/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`). diff --git a/tests/expressions/models.py b/tests/expressions/models.py index 938e623d60..82b9629f81 100644 --- a/tests/expressions/models.py +++ b/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): diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index ed972fd5f7..33c5189390 100644 --- a/tests/expressions/tests.py +++ b/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