#35982: DecimalField.get_db_prep_value() doesn't call adapt_decimalfield_value()
-------------------------------------+-------------------------------------
Reporter: Tim Graham | Owner: Tim
| Graham
Type: Bug | Status: assigned
Component: Database layer | Version: 5.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Tim Graham):
I considered whether an additional test would be useful, but I'm not sure
one could be created for the built-in database backends without resorting
to mocking that checks that `get_db_prep_value()` calls
`adapt_decimalfield_value()`. There are already many failures on django-
mongodb without this patch (and removing the hacky workaround I mentioned
in the description). Example:
{{{
======================================================================
ERROR: test_gt (lookup.test_decimalfield.DecimalFieldLookupTests.test_gt)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/tim/code/django/tests/lookup/test_decimalfield.py", line 25,
in test_gt
self.assertCountEqual(qs, [self.p3])
File "/opt/python3.12.0/lib/python3.12/unittest/case.py", line 1198, in
assertCountEqual
first_seq, second_seq = list(first), list(second)
^^^^^^^^^^^
File "/home/tim/code/django/django/db/models/query.py", line 400, in
__iter__
self._fetch_all()
File "/home/tim/code/django/django/db/models/query.py", line 1928, in
_fetch_all
self._result_cache = list(self._iterable_class(self))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/code/django/django/db/models/query.py", line 91, in
__iter__
results = compiler.execute_sql(
^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/code/django-mongodb/django_mongodb/compiler.py", line
255, in execute_sql
cursor = query.get_cursor()
^^^^^^^^^^^^^^^^^^
File "/home/tim/code/django-mongodb/django_mongodb/query.py", line 19,
in wrapper
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/code/django-mongodb/django_mongodb/query.py", line 74,
in get_cursor
return self.compiler.collection.aggregate(self.get_pipeline())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/collection.py", line 2958, in aggregate
return self._aggregate(
^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/_csot.py", line 119, in csot_wrapper
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/collection.py", line 2866, in _aggregate
return self._database.client._retryable_read(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/mongo_client.py", line 1863, in
_retryable_read
return self._retry_internal(
^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/_csot.py", line 119, in csot_wrapper
return func(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/mongo_client.py", line 1830, in
_retry_internal
).run()
^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/mongo_client.py", line 2554, in run
return self._read() if self._is_read else self._write()
^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/mongo_client.py", line 2697, in _read
return self._func(self._session, self._server, conn, read_pref) #
type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/aggregation.py", line 164, in get_cursor
result = conn.command(
^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/helpers.py", line 45, in inner
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/pool.py", line 566, in command
self._raise_connection_failure(error)
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/pool.py", line 538, in command
return command(
^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/synchronous/network.py", line 158, in command
request_id, msg, size, max_doc_size = message._op_msg(
^^^^^^^^^^^^^^^^
File "/home/tim/.virtualenvs/django312/lib/python3.12/site-
packages/pymongo/message.py", line 415, in _op_msg
return _op_msg_uncompressed(flags, command, identifier, docs, opts)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bson.errors.InvalidDocument: cannot encode object: Decimal('0'), of type:
<class 'decimal.Decimal'>
}}}
It raises the question of whether built-in database backends get special
testing treatment. If this bug manifested on Oracle, for example, I don't
think we would require a regression test for SQLite. I'm comfortable with
running the existing tests with django-mongodb to ensure this issue does
not regress.
--
Ticket URL: <
https://code.djangoproject.com/ticket/35982#comment:3>