Skip to content

Fixed #17854 -- Added database-specific validation for DecimalField max_digits and decimal_places limits. #19654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

ApartPercentage
Copy link

Trac ticket number

Ticket-17854

Branch description

Add database-specific DecimalField validation for precision limits

Add warnings when DecimalField max_digits/decimal_places exceed database limits:

  • MySQL: 65 total digits
  • PostgreSQL: 131072 before decimal, 16383 after
  • Oracle: 38 precision, 127 scale
  • SQLite: 15 significant digits (precision loss)

Includes tests and documentation updates.

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! Thank you for your contribution 💪

As it's your first contribution be sure to check out the patch review checklist.

If you're fixing a ticket from Trac make sure to set the "Has patch" flag and include a link to this PR in the ticket!

If you have any design or process questions then you can ask in the Django forum.

Welcome aboard ⛵️!

Comment on lines +32 to +41
errors.append(
checks.Warning(
"%s does not support DecimalField with max_digits > 38."
% self.connection.display_name,
obj=field,
id="oracle.W001",
)
)

if field.decimal_places > 127:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to create, per database backend, constants variables at module or class scopes for the values used to verify the max_digits and decimal_places, and then reuse them in validation and messages?

Okay, maybe the only benefit of this is the reduction in duplication of hardcoded numbers in the codebase and messages and the reduction in the number of places that need to be changed if a new database version changes it limits.

Another question is whether the constant variables should be in the public API or in the private API of the database backend.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup absolutely these magic numbers would need to be removed 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should set something like max_digits = None and max_decimal_places = None to django.db.backends.base.features.BaseDatabaseFeatures and update these for the specific backends
This also means if the backend changes the limit, we can calculate it based off the database version (as we do with other flags here)

I also think the validation should be within django.db.models.fields.DecimalField._check_decimal_places and django.db.models.fields.DecimalField._check_max_digits. You can look at the GeneratedField checks for inspiration on getting database specific validation

Also think that the error id's should be within fields and documented once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants