#36233: Specific DecimalField with integer part longer than 15 digits can be stored but not retrieved on SQLite -------------------------------------+------------------------------------- Reporter: Orazio | Owner: (none) Type: Bug | Status: new Component: Database layer | Version: dev (models, ORM) | Severity: Normal | Resolution: Keywords: sqlite, orm, | Triage Stage: Accepted decimalfield, invalidoperation | Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+------------------------------------- Comment (by Hridesh MG):
Hi there, I'm new to django contributions (and the ORM internals in general) but what I've gathered so far from my testing is that the quantize() operation fails because the number it is trying to quantize has a precision larger than the context variable passed to it allows. **Model Definition:** {{{ class Apple(models.Model): weight = models.DecimalField(max_digits=16, decimal_places=2) }}} **Relevant block of code in sqlite3/operations.py** {{{ def get_decimalfield_converter(self, expression): # SQLite stores only 15 significant digits. Digits coming from # float inaccuracy must be removed. create_decimal = decimal.Context(prec=15).create_decimal_from_float if isinstance(expression, Col): quantize_value = decimal.Decimal(1).scaleb( -expression.output_field.decimal_places ) def converter(value, expression, connection): if value is not None: return create_decimal(value).quantize( quantize_value, context=expression.output_field.context ) else: def converter(value, expression, connection): if value is not None: return create_decimal(value) return converter }}} **The context variable passed to quantize() (expression.output_field.context)**: {{{ Context(prec=16, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow]) }}} ---- As we can see, the context variable passed to quantize() expects the result of the quantization to have a precision of 16, however, if the input is 9999999999999999 (16 digits), the actual number of significant digits after the quantize operation becomes 18 (9999999999999999.00). This will raise an InvalidOperation exception, see - [https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize] In the scenario where decimal_places is 0 and the input is 9999999999999999 (16 digits) the result of the quantization is 10000000000000000 (17 digits), i assume this is because of SQLite's quirk of only preserving the first 15 significant bits. So the root cause is the same for both errors. ---- I hope the above made sense. I'm not sure what approach I should follow to fix this issue, should we prevent the user from entering a value which has more significant digits than SQLite can handle or should we modify the precision that quantize() expects? Any pointers would be appreciated! -- Ticket URL: <https://code.djangoproject.com/ticket/36233#comment:7> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/django-updates/01070195705d4643-156e3e2c-54a0-4c59-ac61-90ca47985181-000000%40eu-central-1.amazonses.com.