• 
      

    Track unique indexes separately from normal indexes in the database state.

    Review Request #12276 — Created May 13, 2022 and submitted

    Information

    Django Evolution
    release-2.x

    Reviewers

    DatabaseState has previously tracked indexes and unique indexes
    together in a single dictionary. If there were normal and unique indexes
    with the same name, they'd conflict.

    While it makes sense for them to conflict, this actually poses an issue
    on Django 1.6, at least in unit tests. Django 1.6 doesn't consider the
    unique flag when generating an index name, meaning that two indexes
    for the same field with different unique flags end up generating the
    same name.

    If applying an evolution that, say, turns off db_index and turns on
    unique, we end up in a state where DatabaseState is aware of the
    previous index from the db_index and returns it when looking to see if
    there's a unique index present. The query we have is really asking "is
    there a unique index for <columns>" and, if no, adding the unique index
    for tracking. Since both used the same names, these lookups failed.

    Django 1.7 and higher use different naming for unique indexes, so the
    problem doesn't exist there. While ideally we'd just override the index
    name generation for 1.6, we do need to be compliant with Django 1.6's
    built-in logic or other things will fail. So separating out this state
    is the cleanest (and hopefully safest) way of ensuring we can look up
    and apply the correct state.

    All unit tests pass for all versions of Django.

    Summary ID
    Track unique indexes separately from normal indexes in the database state.
    `DatabaseState` has previously tracked indexes and unique indexes together in a single dictionary. If there were normal and unique indexes with the same name, they'd conflict. While it makes sense for them to conflict, this actually poses an issue on Django 1.6, at least in unit tests. Django 1.6 doesn't consider the `unique` flag when generating an index name, meaning that two indexes for the same field with different `unique` flags end up generating the same name. If applying an evolution that, say, turns off `db_index` and turns on `unique`, we end up in a state where `DatabaseState` is aware of the previous index from the `db_index` and returns it when looking to see if there's a unique index present. The query we have is really asking "is there a unique index for <columns>" and, if no, adding the unique index for tracking. Since both used the same names, these lookups failed. Django 1.7 and higher use different naming for unique indexes, so the problem doesn't exist there. While ideally we'd just override the index name generation for 1.6, we do need to be compliant with Django 1.6's built-in logic or other things will fail. So separating out this state is the cleanest (and hopefully safest) way of ensuring we can look up and apply the correct state.
    2641011a97cc7daafa232679d3a2cefd1c50392b
    david
    1. Ship It!
    2. 
        
    chipx86
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-2.x (e8a57e7)