Opened 90 minutes ago
Last modified 25 minutes ago
#37006 new Bug
Attempting to recreate the PK in a model with no other fields generates a migration that crashes on SQLite
| Reported by: | Carol Naranjo | Owned by: | |
|---|---|---|---|
| Component: | Migrations | Version: | 6.0 |
| Severity: | Normal | Keywords: | sqlite, migrations |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When a model contains no fields other than the primary key, and the PK is recreated (e.g., renaming and switching from an AutoField to a UUIDField), Django generates a migration with two operations: RemoveField followed by AddField.
In SQLite, applying this migration fails because SQLite cannot create a table with no columns. It only affects SQLite because in other databases the table can be altered by droping the column, whereas SQLite requires that a new table is created and then the data is copied.
Steps to reproduce:
- Starting with a model with only the primary key:
class Place(models.Model): pass # PK is created by default as AutoField with column name "id"
- Modify the primary key:
class Place(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
- Run
makemigrations. Which generates following migration:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='place',
name='id',
),
migrations.AddField(
model_name='place',
name='uid',
field=models.AutoField(primary_key=True, serialize=False),
),
]
- Apply the migration using SQLite.
Observed behavior:
During the RemoveField operation, the generated migration tries to create a table with zero non-PK columns, resulting in:
CREATE TABLE "new__myapp_place" (); (params None)
sqlite3.OperationalError: near ")": syntax error
Expected behavior:
SQLite migration should not crash. Either prevent a migration that would create a table with zero columns or handle it gracefully.
On a side note: This is an edge case—tables without additional fields are rare—but it still causes an unexpected crash.
Change History (2)
comment:1 by , 63 minutes ago
| Component: | Database layer (models, ORM) → Migrations |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:2 by , 25 minutes ago
Related tickets are #22997 and #29790.
The way SQLite requires the table to be rebuilt on field removal and alterations would likely force us to add a _django_empty_col column to support this workflow.
There might be a way to approach this at the auto-detector level by turning a removal and addition of a Field(primary_key=True) with a different name as a [AlterField, RenameField] instead of a [RemoveField, AddField]. Since a model/table can only have one primary key at a time that seems like a better way to approach this problem as it would then allow us to focus our efforts on getting AlterField(from_pk, to_pk) to work in most cases which is what #29790 is about.
Thanks, reproduced at f6167b8bc881babd19b67c004e8f37954afc192e. Looks like another circumstance that manifests the failure described in #24424.