Opened 5 years ago
Closed 4 years ago
#31487 closed New feature (fixed)
Add support for precision argument to Round
Reported by: | Baptiste Mispelon | Owned by: | Nick Pope |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | database function, round, precision, decimal places |
Cc: | pope1ni | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Django's Round
function currently only supports rounding to the nearest integer. If you need to round to a more specific precision you need to roll out your own solution.
But as far as I can tell, all backends natively supported by Django support a second argument to Round
:
- Postgres: https://www.postgresql.org/docs/12/functions-math.html#FUNCTIONS-MATH-FUNC-TABLE
- Sqlite: https://sqlite.org/lang_corefunc.html#round
- MySQL: https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_round
- Oracle: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions135.htm
In my project (postgres only) my work around was to declare my own custom function:
class Round(Func): function = 'ROUND' arity = 2
But having this built-in would be quite useful.
Change History (10)
comment:1 by , 5 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
follow-up: 4 comment:3 by , 5 years ago
Cc: | added |
---|
comment:4 by , 5 years ago
Replying to felixxm:
Please take into account that it was discussed in the original PR, and we decided to leave
Round()
without a precision because it can be unstable around0.5
.
What does "unstable around 0.5" mean? I assume it has something to do with what Python call rounding modes [1] but if that's the case I don't understand why that wouldn't also apply to rounding to integers.
The comment you link doesn't have a lot of information and itself links to another comment about Spatialite which doesn't really clarify much.
Navigating the discussion on the PR is a bit hard but searching for the word "round" in the commit history of the PR I found https://github.com/django/django/pull/9622/commits/5acc1162a716c4ff6fcb0bca32840e11d6585c7e.
The warning added in that commit seems like it was not integrated into the final commit (I searched Django's history with git log -S "equally close" -- docs/
to try and find it) but I can't find a comment explaining the decision to remove it.
Edit
While searching for more information about rounding modes in different databases, I found a useful reference of different rounding modes and their results when applied to various inputs: https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html
[1] https://docs.python.org/3/library/decimal.html#rounding-modes
comment:5 by , 5 years ago
The comment you link doesn't have a lot of information and itself links to another comment about Spatialite which doesn't really clarify much.
Agreed, that's why I CC'ed Nick, maybe he remember rationales.
comment:6 by , 4 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:7 by , 4 years ago
Has patch: | set |
---|---|
Keywords: | database function round precision decimal places added |
Owner: | set to |
Status: | new → assigned |
Version: | 3.0 → dev |
For once, I can't remember exactly why we didn't do this, hence my opening of the duplicate ticket #32592 yesterday looking to fix exactly this issue.
I can think of a number of possible reasons based on the discussions and looking at the existing code:
- Something to do with the rounding issue around
0.5
. (I don't think this should stop us supporting the second argument. We already mention it in the documentation.) - Something to do with
Round
being aTransform
which setsarity = 1
. (This can be overridden back toNone
while still allowing the transform to work.) - Something to do with SpatiaLite. I'm not sure what that comment was about as SQLite and SpatialLite behave the same and the function is available in SQLite.
- The SQLite version of
ROUND()
does not support negative precision values.
Anyway, here is a PR.
comment:8 by , 4 years ago
Patch needs improvement: | set |
---|
comment:9 by , 4 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Please take into account that it was discussed in the original PR, and we decided to leave
Round()
without a precision because it can be unstable around0.5
.