Changes between Version 37 and Version 41 of Ticket #36030


Ignore:
Timestamp:
Nov 25, 2025, 6:56:58 AM (5 days ago)
Author:
Bob Kline
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #36030

    • Property Status newassigned
    • Property Summary SQLite backend: division with Decimal("x.0") operand and integer operand fails to preserve precisionSQLite backend: division with Decimal("x.0") operand discards fractional portion of result
    • Property Needs tests set
    • Property Owner set to VIZZARD-X
    • Property Keywords sqlite added
  • Ticket #36030 – Description

    v37 v41  
    11== Expected Behavior ==
    2 When division is performed in Django, and at least one of the operands is a `decimal.Decimal` value created using the string constructor with at least one digit following the decimal point (for example, `Decimal("3.0")`), the precision of the result should be preserved. For example, `2 / Decimal("3.0")` should produce a value close to `0.6667`.
     2When division is performed in Django, and at least one of the operands is a `decimal.Decimal` value created using the string constructor with at least one digit following the decimal point (for example, `Decimal("3.0")`), the fractional portion of the result should be retained. For example, `2 / Decimal("3.0")` should produce a value close to `0.6667`.
    33
    44== Observed Behavior ==
    5 When such a division is performed using the SQLite backend and one of the operands is an integer, integer ("floor") division is performed unless the decimal value has a non-zero fractional part. For example, `2 / Decimal("3.1")` produces `0.64516129032258064516`, but `2 / Decimal("3.0")` produces `0`.
     5When such a division is performed using the SQLite backend, integer ("floor") division is performed unless the decimal value has a non-zero fractional part. For example, `2 / Decimal("3.1")` produces `0.64516129032258064516`, but `2 / Decimal("3.0")` produces `0`.
    66
    77== Repro Case ==
     
    3434    cursor.execute(f"SELECT {sql}", params)
    3535    result = cursor.fetchone()[0]
    36     print("result:", result). # prints 0
     36    print("result:", result). # -> result: 0
    3737}}}
    3838
    3939== Notes ==
    40 The original ticket reported that division using PostgreSQL as the backend did not consistently preserve precision when the denominator was a `Decimal` value. Further investigation confirmed that the same problem arises with SQLite, and that the inconsistent behavior is observed whether the `Decimal` operand is the numerator or the denominator. Testing showed that the other three officially supported database backends all preserve decimal precision in much the same way as native Python division mixing integer and decimal operands.
     40This ticket originally reported that division using PostgreSQL as the backend did not consistently preserve precision when the denominator was a `Decimal` value. Further investigation confirmed that the same problem arises with SQLite, and that the inconsistent behavior is observed whether the `Decimal` operand is the numerator or the denominator. Testing showed that the other three officially supported database backends all preserve decimal precision in much the same way as native Python division mixing integer and decimal operands.
    4141
    42 It has been decided that Django does not need to enforce consistent division behavior across all backends, as long as there is a way to force preservation of precision. With PostgreSQL, precision is preserved if the `Decimal` value is created with the string constructor and includes at least one digit after the decimal point (e.g., `Decimal("3.0")`). With SQLite, even `Decimal("3.0")` fails to preserve precision. Therefore, the scope of this ticket has been narrowed to address only the behavior of the SQLite driver.
     42It has been decided that Django does not need to enforce consistent division behavior across all backends, as long as there is a way to force preservation of the fractional portion of the result. With PostgreSQL, this is achieved if the `Decimal` value is created with the string constructor and includes at least one digit after the decimal point (e.g., `Decimal("3.0")`). With SQLite, even `Decimal("3.0")` fails to preserve the fractional portion of the result of the division operation. Therefore, the scope of this ticket has been narrowed to address only the behavior of the SQLite driver.
     43
     44Note that the [https://docs.djangoproject.com/en/5.2/ref/databases/#sqlite-decimal-handling Django documentation for decimal handling using the SQLite backend] says that for this backend "Decimal values are internally converted to the `REAL` data type."
    4345
    4446It was further decided that the user documentation should ''not'' describe the remaining inconsistencies between backends.
Back to Top