#34058: Upgrading to Django 4.1, then widening AutoField to BigAutoField, fails 
to
widen the corresponding sequence
-------------------------------------+-------------------------------------
               Reporter:  Anders     |          Owner:  nobody
  Kaseorg                            |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  4.1
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 #30511 changed the behavior of migrations that widen `AutoField`, removing
 the code that updates the type of the corresponding sequence. This creates
 a problem in projects that were upgraded from Django 4.0 or earlier, where
 the `AutoField`s will still be `serial` columns, and then migrated in
 Django 4.1, where the sequence will not be updated automatically.

 Here’s a self-contained reproduction recipe:

 1. Install an old version of Django:
    {{{
    #!console
    $ pip install django==4.0.7 psycopg2-binary
    }}}
 2. Create a minimal test project:
    {{{
    #!python
    # manage.py
    import os, sys
    from django.core.management import execute_from_command_line
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_settings")
    execute_from_command_line(sys.argv)
    }}}
    {{{
    #!python
    # my_settings.py
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": "my_database",
        }
    }
    INSTALLED_APPS = ["my_app"]
    }}}
    {{{
    #!python
    # my_app/models.py
    from django.db import models
    class Widget(models.Model):
        id = models.SmallAutoField(primary_key=True)
    }}}
 3. Create the PostgreSQL database and run migrations:
    {{{
    #!console
    $ createdb my_database
    $ python manage.py makemigrations my_app
    Migrations for 'my_app':
      my_app/migrations/0001_initial.py
        - Create model Widget
    $ python manage.py migrate
    Operations to perform:
      Apply all migrations: my_app
    Running migrations:
      Applying my_app.0001_initial... OK
    }}}
 4. Upgrade to Django 4.1:
    {{{
    #!console
    $ pip install Django==4.1
    }}}
 5. Edit `my_app/models.py` to widen the field from `SmallAutoField` to
 `BigAutoField`:
    {{{
    #!python
    # my_app/models.py
    from django.db import models
    class Widget(models.Model):
        id = models.BigAutoField(primary_key=True)
    }}}
 6. Run migrations:
    {{{
    #!console
    $ ./manage.py makemigrations
    Migrations for 'my_app':
      my_app/migrations/0002_alter_widget_id.py
        - Alter field id on widget
    $ ./manage.py migrate
    Operations to perform:
      Apply all migrations: my_app
    Running migrations:
      Applying my_app.0002_alter_widget_id... OK
    }}}
 7. Observe that the field has been widened but the sequence corresponding
 to it has not:
    {{{
    #!console
    $ ./manage.py dbshell
    psql (14.5, server 13.8)
    Type "help" for help.

    my_database=> \d my_app_widget
                                Table "public.my_app_widget"
     Column |  Type  | Collation | Nullable |                  Default
 
--------+--------+-----------+----------+-------------------------------------------
     id     | bigint |           | not null |
 nextval('my_app_widget_id_seq'::regclass)
    Indexes:
        "my_app_widget_pkey" PRIMARY KEY, btree (id)

    my_database=> \d my_app_widget_id_seq
                   Sequence "public.my_app_widget_id_seq"
       Type   | Start | Minimum | Maximum | Increment | Cycles? | Cache
    ----------+-------+---------+---------+-----------+---------+-------
     smallint |     1 |       1 |   32767 |         1 | no      |     1
    Owned by: public.my_app_widget.id
    }}}
 8. Try and fail to create a large number of rows:
    {{{
    #!console
    $ ./manage.py shell
    Python 3.10.6 (main, Aug  1 2022, 20:38:21) [GCC 11.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from my_app.models import Widget
    >>> Widget.objects.bulk_create(Widget() for i in range(40000))
    Traceback (most recent call last):
      File "…/lib/python3.10/site-packages/django/db/backends/utils.py",
 line 89, in _execute
        return self.cursor.execute(sql, params)
    psycopg2.errors.SequenceGeneratorLimitExceeded: nextval: reached
 maximum value of sequence "my_app_widget_id_seq" (32767)


    The above exception was the direct cause of the following exception:
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    …
      File "…/lib/python3.10/site-packages/django/db/backends/utils.py",
 line 89, in _execute
        return self.cursor.execute(sql, params)
    django.db.utils.DataError: nextval: reached maximum value of sequence
 "my_app_widget_id_seq" (32767)
    }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34058>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018381b1cb27-88bc9d00-170b-4961-8fdc-4a46252929e9-000000%40eu-central-1.amazonses.com.

Reply via email to