Opened 2 months ago

Last modified 5 weeks ago

#36030 assigned Bug

Rendering decimal to SQL is incoherent and leads to bugs. It relays on str formating not type. — at Version 4

Reported by: Bartłomiej Nowak Owned by:
Component: Database layer (models, ORM) Version: 5.1
Severity: Normal Keywords:
Cc: Bartłomiej Nowak Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Bartłomiej Nowak)

When I am using Decimal at Python level, I expect to use numeric type on database level. But it seems to depend on string formatting of decimal itself instead of type of object.

See examples:

Decimal(1000.0) --> will render as 1000 at query and will be INT on db level.
Decimal(1000) --> will render as 1000 at query and will be INT on db level.
Decimal("1000.0") -> will render as 1000,0 at query and will be NUMERIC on db level.
models.Value(1000.0, output_field=DecimalField()) -> will render as 1000 at query and will be INT on db level.
models.Value(1000.0) (no decimal provided as above) -> will render as 1000,0 at query and will be NUMERIC on db level.

It leads to bugs, cuz at DB LVL, INT / INT is also INT (2/3 = 0), and I doubt anyone who provides decimal there, excepts that behavior.

=============
I am using Postgres.

SomeModel.objects.create(some_field_of_type_int=2)
sm = SomeModel.objects.annotate(x=F("some_field_of_type_int") / Decimal(3.0)).get()
sm.x # returns 0

It will render Decimal of 3.0 to the query as 3 (INT). Because str(...) from Decimal(3.0) returns 3. (See cases at description)
At python is not a problem, but at database it is, cus it breaks types. Calculation of two INTs at postgres, will return int as well, which is in this case 0, instead of 0.6666, which database would produce, if Django would render 3.0 instead of 3.

Therefore, Django will return Decimal('0'), which I consider as Bug. This is not what anyone suppose to get.
=============

Change History (4)

comment:1 by Tim Graham, 2 months ago

Which database are you using? Can you give examples of the specific querysets and the expected results?

comment:2 by Natalia Bidart, 2 months ago

Resolution: needsinfo
Status: newclosed

Closing as needsinfo, Bartłomiej Nowak please reopen when you can provide further details as requested. A way to reproduce would be crucial. Thank you!

comment:3 by Bartłomiej Nowak, 2 months ago

I am using Postgres.

SomeModel.objects.create(some_field_of_type_int=2)
sm = SomeModel.objects.annotate(x=F("some_field_of_type_int") / Decimal(3.0)).get()
sm.x # returns 0

It will render Decimal of 3.0 to the query as 3 (INT). Because str(...) from Decimal(3.0) returns 3. (See cases at description)
At python is not a problem, but at database it is, cus it breaks types. Calculation of two INTs at postgres, will return int as well, which is in this case 0, instead of 0.6666, which database would produce, if Django would render 3.0 instead of 3.

Therefore, Django will return Decimal('0'), which I consider as Bug. This is not what anyone suppose to get.

comment:4 by Bartłomiej Nowak, 2 months ago

Description: modified (diff)
Resolution: needsinfo
Status: closednew
Note: See TracTickets for help on using tickets.
Back to Top