#37351 new Bug

Altering the null attribute of a GeneratedField should raise when making migrations

Reported by: Jacob Walls Owned by:
Component: Database layer (models, ORM) Version: 6.1
Severity: Normal Keywords:
Cc: Natalia Bidart Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The migration layer attempts to detect if a GeneratedField has been altered in a SQL-affecting way so that it can throw an exception:

        if modifying_generated_field:
            raise ValueError(
                f"Modifying GeneratedFields is not supported - the field {new_field} "
                "must be removed and re-added with the new definition."
            )

However, altering the null kwarg, e.g. from False to True is not detected by the above check, but does have an incidence on the DDL that gets emitted, so a migration gets emitted that can do wacky things in the database, see ticket:37348#comment:6.

I propose to fix the modifying_generated_field logic so that it fathoms changes in the null attribute and raises.

This will be a breaking change but most likely a welcome one (removing dangerous operations from your migrations).

Rough test:

  • tests/migrations/test_operations.py

    diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
    index 9bbf1249e9..907c255e22 100644
    a b class OperationTests(OperationTestBase):  
    66466646            tests.append(
    66476647                ("test_igfc_4", generated_1, generated_3),
    66486648            )
     6649        generated_4 = models.GeneratedField(
     6650            expression=F("pink") + F("pink") + F("pink"),
     6651            output_field=models.IntegerField(),
     6652            db_persist=db_persist,
     6653            null=True,
     6654        )
     6655        tests.append(("test_igfc_5", generated_2, generated_4))
    66496656        for app_label, add_field, alter_field in tests:
    66506657            project_state = self.set_up_test_model(app_label)
    66516658            operations = [
AssertionError: ValueError not raised

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top