[Django] #37006: Attempting to recreate the PK in a model with no other fields generates a migration that crashes on SQLite

12 views
Skip to first unread message

Django

unread,
11:20 AM (7 hours ago) 11:20 AM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
-------------------------------------+-------------------------------------
Reporter: Carol Naranjo | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: 6.0 | Severity: Normal
Keywords: sqlite, migrations | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
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:**

1. 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"
}}}

2. Modify the primary key:
{{{
class Place(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
}}}

3. 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),
),
]
}}}


4. 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.
--
Ticket URL: <https://code.djangoproject.com/ticket/37006>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
11:47 AM (7 hours ago) 11:47 AM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
------------------------------------+------------------------------------
Reporter: Carol Naranjo | Owner: (none)
Type: Bug | Status: new
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+------------------------------------
Changes (by Jacob Walls):

* component: Database layer (models, ORM) => Migrations
* stage: Unreviewed => Accepted

Comment:

Thanks, reproduced at f6167b8bc881babd19b67c004e8f37954afc192e. Looks like
another circumstance that manifests the failure described in #24424.
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:1>

Django

unread,
12:25 PM (6 hours ago) 12:25 PM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
------------------------------------+------------------------------------
Reporter: Carol Naranjo | Owner: (none)
Type: Bug | Status: new
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+------------------------------------
Comment (by Simon Charette):

Related tickets are #22997 and #29790.

The way SQLite [https://sqlite.org/lang_altertable.html 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.
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:2>

Django

unread,
1:16 PM (5 hours ago) 1:16 PM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
------------------------------------+------------------------------------
Reporter: Carol Naranjo | Owner: (none)
Type: Bug | Status: new
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------------+------------------------------------
Comment (by Carol Naranjo):

Replying to [comment:1 Jacob Walls]:
> Thanks, reproduced at f6167b8bc881babd19b67c004e8f37954afc192e. Looks
like another circumstance that manifests the failure described in #24424.
Hi Jacob, can you double check the commit link? it seems unrelated.

---

Replying to [comment:2 Simon Charette]:
>
> 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]`.

Hi Simon, I like that approach. If it’s not time-sensitive, I’d be happy
to work on a fix and assign the ticket to myself.
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:3>

Django

unread,
1:20 PM (5 hours ago) 1:20 PM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
-------------------------------------+-------------------------------------
Reporter: Carol Naranjo | Owner: Carol
| Naranjo
Type: Bug | Status: assigned
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* owner: (none) => Carol Naranjo
* status: new => assigned

Comment:

Oh it's definitely unrelated. I wasn't blaming that commit, I was just
leaving a reference in case it's retriaged a few years from now and we
can't reproduce.

> If it’s not time-sensitive, I’d be happy to work on a fix and assign the
ticket to myself.

Not time-sensitive, thanks for the offer!
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:4>

Django

unread,
1:21 PM (5 hours ago) 1:21 PM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
-------------------------------------+-------------------------------------
Reporter: Carol Naranjo | Owner: Carol
| Naranjo
Type: Bug | Status: assigned
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Simon Charette):

Sure thing Carol, please assign the ticket to yourself and take some time
to read [https://docs.djangoproject.com/en/6.0/internals/contributing/ the
contribution guidelines].

You'll like be looking at code living in `autodetector.py` and associated
tests in `tests/migrations/test_autodetector.py`.
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:5>

Django

unread,
1:36 PM (5 hours ago) 1:36 PM
to django-...@googlegroups.com
#37006: Attempting to recreate the PK in a model with no other fields generates a
migration that crashes on SQLite
-------------------------------------+-------------------------------------
Reporter: Carol Naranjo | Owner: Carol
| Naranjo
Type: Bug | Status: assigned
Component: Migrations | Version: 6.0
Severity: Normal | Resolution:
Keywords: sqlite, migrations | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Carol Naranjo):

@Jacob, ah got you, thanks for the clarification :)

Thanks for the hint Simon!
--
Ticket URL: <https://code.djangoproject.com/ticket/37006#comment:6>
Reply all
Reply to author
Forward
0 new messages