#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.